1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
24 #include "wx/dcclient.h"
28 #include "wx/notebook.h"
29 #include "wx/statusbr.h"
31 #include "wx/gtk/win_gtk.h"
32 #include "gdk/gdkprivate.h"
33 #include "gdk/gdkkeysyms.h"
37 //-----------------------------------------------------------------------------
38 // documentation on internals
39 //-----------------------------------------------------------------------------
42 I have been asked several times about writing some documentation about
43 the GTK port of wxWindows, especially its internal structures. Obviously,
44 you cannot understand wxGTK without knowing a little about the GTK, but
45 some more information about what the wxWindow, which is the base class
46 for all other window classes, does seems required as well.
48 What does wxWindow do? It contains the common interface for the following
49 jobs of its descentants:
51 1) Define the rudimentary behaviour common to all window classes, such as
52 resizing, intercepting user input so as to make it possible to use these
53 events for special purposes in a derived class, window names etc.
55 2) Provide the possibility to contain and manage children, if the derived
56 class is allowed to contain children, which holds true for those window
57 classes, which do not display a native GTK widget. To name them, these
58 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
59 work classes are a special case and are handled a bit differently from
62 3) Provide the possibility to draw into a client area of a window. This,
63 too, only holds true for classes that do not display a native GTK widget
66 4) Provide the entire mechanism for scrolling widgets. This actaul inter-
67 face for this is usually in wxScrolledWidget, but the GTK implementation
70 5) A multitude of helper or extra methods for special purposes, such as
71 Drag'n'Drop, managing validators etc.
73 Normally one might expect, that one wxWindows class would always contain
74 one GTK widget. Under GTK, there is no such allround widget that has all
75 the functionality. Moreover, the GTK defines a client area as a different
76 widget from the actual widget you are handling. Last but not least some
77 special classes (e.g. wxFrame) handle different categories of widgets and
78 still have the possibility to draw something in the client area.
79 It was therefore required to write a special purpose GTK widget, that would
80 represent a client area in the sense of wxWindows capable to do the jobs
81 2), 3) and 4). I have written this class and it resides in win_gtk.c of
84 All windows must have a widget, with which they interact with other under-
85 lying GTK widget. It is this widget, e.g. that has to be resized etc and
86 thw wxWindow class has a member variable called m_widget which holds a
87 pointer to this widget. When the window class displays a GTK native widget,
88 this is the only GTK widget the class manages. When the class has a client
89 area for drawing into and for containing children it must have at least
90 one more GTK widget to handle (of the type GtkMyFixed, defined in win_gtk.c),
91 but there can be any number of widgets, handled by a class (e.g. the frame
92 class handles three). The common rule for all windows is only, that the
93 widget that interacts with the rest of GTK must be referenced in m_widget
94 and all other widgets must be children of this widget on the GTK level.
95 The top-most widget, which also represents the client area, must be in
96 the m_wxwindow field and must be of the type GtkMyFixed.
98 As I said, the window classes that display a GTK native widget only have
99 one widget, so in the case of e.g. the wxButton class m_widget holds a
100 pointer to a GtkButton widget. But windows with client areas (for drawing
101 and children) have a m_widget field that is a pointer to a GtkScrolled-
102 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
103 one is (in the GTK sense) a child of the GtkScrolledWindow.
105 If the m_wxwindow field is set, then all input to this widget is inter-
106 cepted and sent to the wxWindows class. If not, all input to the widget
107 that gets pointed to by m_widget gets intercepted and sent to the class.
111 //-----------------------------------------------------------------------------
113 //-----------------------------------------------------------------------------
115 extern wxList wxPendingDelete
;
116 extern wxList wxTopLevelWindows
;
117 extern bool g_blockEventsOnDrag
;
118 static bool g_capturing
= FALSE
;
120 // hack: we need something to pass to gtk_menu_popup, so we store the time of
121 // the last click here
122 static guint32 gs_timeLastClick
= 0;
124 //-----------------------------------------------------------------------------
125 // "expose_event" (of m_wxwindow, not of m_widget)
126 //-----------------------------------------------------------------------------
128 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
130 if (!win
->HasVMT()) return;
131 if (g_blockEventsOnDrag
) return;
133 win
->m_updateRegion
.Union( gdk_event
->area
.x
,
135 gdk_event
->area
.width
,
136 gdk_event
->area
.height
);
138 if (gdk_event
->count
> 0) return;
141 printf( "OnExpose from " );
142 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
143 printf( win->GetClassInfo()->GetClassName() );
147 wxPaintEvent
event( win
->GetId() );
148 event
.SetEventObject( win
);
149 win
->GetEventHandler()->ProcessEvent( event
);
151 win
->m_updateRegion
.Clear();
154 //-----------------------------------------------------------------------------
155 // "draw" (of m_wxwindow, not of m_widget)
156 //-----------------------------------------------------------------------------
158 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
160 if (!win
->HasVMT()) return;
161 if (g_blockEventsOnDrag
) return;
163 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
165 wxPaintEvent
event( win
->GetId() );
166 event
.SetEventObject( win
);
167 win
->GetEventHandler()->ProcessEvent( event
);
169 win
->m_updateRegion
.Clear();
172 //-----------------------------------------------------------------------------
174 //-----------------------------------------------------------------------------
176 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
178 if (!win
->HasVMT()) return FALSE
;
179 if (g_blockEventsOnDrag
) return FALSE
;
182 printf( "OnKeyPress from " );
183 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
184 printf( win->GetClassInfo()->GetClassName() );
189 switch (gdk_event
->keyval
)
191 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
192 case GDK_Tab
: key_code
= WXK_TAB
; break;
193 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
194 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
195 case GDK_Return
: key_code
= WXK_RETURN
; break;
196 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
197 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
198 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
199 case GDK_Delete
: key_code
= WXK_DELETE
; break;
200 case GDK_Home
: key_code
= WXK_HOME
; break;
201 case GDK_Left
: key_code
= WXK_LEFT
; break;
202 case GDK_Up
: key_code
= WXK_UP
; break;
203 case GDK_Right
: key_code
= WXK_RIGHT
; break;
204 case GDK_Down
: key_code
= WXK_DOWN
; break;
205 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
206 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
207 case GDK_Next
: key_code
= WXK_NEXT
; break;
208 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
209 case GDK_End
: key_code
= WXK_END
; break;
210 case GDK_Begin
: key_code
= WXK_HOME
; break;
211 case GDK_Select
: key_code
= WXK_SELECT
; break;
212 case GDK_Print
: key_code
= WXK_PRINT
; break;
213 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
214 case GDK_Insert
: key_code
= WXK_INSERT
; break;
215 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
216 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
217 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
218 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
219 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
220 case GDK_KP_Up
: key_code
= WXK_UP
; break;
221 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
222 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
223 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
224 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
225 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
226 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
227 case GDK_KP_End
: key_code
= WXK_END
; break;
228 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
229 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
230 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
231 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
232 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
233 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
234 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
235 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
236 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
237 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
238 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
239 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
240 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
241 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
242 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
243 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
244 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
245 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
246 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
247 case GDK_F1
: key_code
= WXK_F1
; break;
248 case GDK_F2
: key_code
= WXK_F2
; break;
249 case GDK_F3
: key_code
= WXK_F3
; break;
250 case GDK_F4
: key_code
= WXK_F4
; break;
251 case GDK_F5
: key_code
= WXK_F5
; break;
252 case GDK_F6
: key_code
= WXK_F6
; break;
253 case GDK_F7
: key_code
= WXK_F7
; break;
254 case GDK_F8
: key_code
= WXK_F8
; break;
255 case GDK_F9
: key_code
= WXK_F9
; break;
256 case GDK_F10
: key_code
= WXK_F10
; break;
257 case GDK_F11
: key_code
= WXK_F11
; break;
258 case GDK_F12
: key_code
= WXK_F12
; break;
261 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
262 key_code
= gdk_event
->keyval
;
266 if (!key_code
) return FALSE
;
268 wxKeyEvent
event( wxEVT_CHAR
);
269 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
270 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
271 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
272 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
273 event
.m_keyCode
= key_code
;
276 event
.SetEventObject( win
);
278 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
282 wxWindow
*ancestor
= win
;
285 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
288 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
289 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
292 ancestor
= ancestor
->GetParent();
298 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
299 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
305 //-----------------------------------------------------------------------------
306 // "button_press_event"
307 //-----------------------------------------------------------------------------
309 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
311 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
313 if (g_blockEventsOnDrag
) return TRUE
;
317 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
319 gtk_widget_grab_focus (win
->m_wxwindow
);
322 printf( "GrabFocus from " );
323 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
324 printf( win->GetClassInfo()->GetClassName() );
331 if (!win
->HasVMT()) return TRUE
;
334 printf( "OnButtonPress from " );
335 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
336 printf( win->GetClassInfo()->GetClassName() );
340 wxEventType event_type
= wxEVT_LEFT_DOWN
;
342 if (gdk_event
->button
== 1)
344 switch (gdk_event
->type
)
346 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
347 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
351 else if (gdk_event
->button
== 2)
353 switch (gdk_event
->type
)
355 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
356 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
360 else if (gdk_event
->button
== 3)
362 switch (gdk_event
->type
)
364 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
365 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
370 wxMouseEvent
event( event_type
);
371 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
372 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
373 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
374 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
375 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
376 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
377 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
379 event
.m_x
= (long)gdk_event
->x
;
380 event
.m_y
= (long)gdk_event
->y
;
382 // Some control don't have their own X window and thus cannot get
387 wxNode
*node
= win
->GetChildren()->First();
390 wxWindow
*child
= (wxWindow
*)node
->Data();
391 if ((child
->m_x
<= event
.m_x
) &&
392 (child
->m_y
<= event
.m_y
) &&
393 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
394 (child
->m_y
+child
->m_height
>= event
.m_y
))
397 event
.m_x
-= child
->m_x
;
398 event
.m_y
-= child
->m_y
;
405 event
.SetEventObject( win
);
407 gs_timeLastClick
= gdk_event
->time
;
409 if (win
->GetEventHandler()->ProcessEvent( event
))
410 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
415 //-----------------------------------------------------------------------------
416 // "button_release_event"
417 //-----------------------------------------------------------------------------
419 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
421 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
423 if (g_blockEventsOnDrag
) return TRUE
;
425 if (!win
->HasVMT()) return TRUE
;
428 printf( "OnButtonRelease from " );
429 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
430 printf( win->GetClassInfo()->GetClassName() );
434 wxEventType event_type
= wxEVT_NULL
;
436 switch (gdk_event
->button
)
438 case 1: event_type
= wxEVT_LEFT_UP
; break;
439 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
440 case 3: event_type
= wxEVT_RIGHT_UP
; break;
443 wxMouseEvent
event( event_type
);
444 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
445 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
446 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
447 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
448 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
449 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
450 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
451 event
.m_x
= (long)gdk_event
->x
;
452 event
.m_y
= (long)gdk_event
->y
;
454 // Some control don't have their own X window and thus cannot get
459 wxNode
*node
= win
->GetChildren()->First();
462 wxWindow
*child
= (wxWindow
*)node
->Data();
463 if ((child
->m_x
<= event
.m_x
) &&
464 (child
->m_y
<= event
.m_y
) &&
465 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
466 (child
->m_y
+child
->m_height
>= event
.m_y
))
469 event
.m_x
-= child
->m_x
;
470 event
.m_y
-= child
->m_y
;
477 event
.SetEventObject( win
);
479 if (win
->GetEventHandler()->ProcessEvent( event
))
480 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
485 //-----------------------------------------------------------------------------
486 // "motion_notify_event"
487 //-----------------------------------------------------------------------------
489 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
491 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
493 if (g_blockEventsOnDrag
) return TRUE
;
495 if (!win
->HasVMT()) return TRUE
;
498 printf( "OnMotion from " );
499 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
500 printf( win->GetClassInfo()->GetClassName() );
504 wxMouseEvent
event( wxEVT_MOTION
);
505 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
506 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
507 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
508 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
509 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
510 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
511 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
513 event
.m_x
= (long)gdk_event
->x
;
514 event
.m_y
= (long)gdk_event
->y
;
516 // Some control don't have their own X window and thus cannot get
521 wxNode
*node
= win
->GetChildren()->First();
524 wxWindow
*child
= (wxWindow
*)node
->Data();
525 if ((child
->m_x
<= event
.m_x
) &&
526 (child
->m_y
<= event
.m_y
) &&
527 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
528 (child
->m_y
+child
->m_height
>= event
.m_y
))
531 event
.m_x
-= child
->m_x
;
532 event
.m_y
-= child
->m_y
;
539 event
.SetEventObject( win
);
541 if (win
->GetEventHandler()->ProcessEvent( event
))
542 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
547 //-----------------------------------------------------------------------------
549 //-----------------------------------------------------------------------------
551 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
553 if (g_blockEventsOnDrag
) return TRUE
;
556 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
558 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
560 printf( "SetFocus flag from " );
561 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
562 printf( win->GetClassInfo()->GetClassName() );
568 if (!win
->HasVMT()) return TRUE
;
571 printf( "OnSetFocus from " );
572 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
573 printf( win->GetClassInfo()->GetClassName() );
575 printf( WXSTRINGCAST win->GetLabel() );
579 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
580 event
.SetEventObject( win
);
582 if (win
->GetEventHandler()->ProcessEvent( event
))
583 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
588 //-----------------------------------------------------------------------------
590 //-----------------------------------------------------------------------------
592 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
594 if (g_blockEventsOnDrag
) return TRUE
;
597 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
598 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
601 if (!win
->HasVMT()) return TRUE
;
604 printf( "OnKillFocus from " );
605 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
606 printf( win->GetClassInfo()->GetClassName() );
610 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
611 event
.SetEventObject( win
);
613 if (win
->GetEventHandler()->ProcessEvent( event
))
614 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
619 //-----------------------------------------------------------------------------
620 // "enter_notify_event"
621 //-----------------------------------------------------------------------------
623 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
625 if (widget
->window
!= gdk_event
->window
) return TRUE
;
627 if (g_blockEventsOnDrag
) return TRUE
;
629 if (!win
->HasVMT()) return TRUE
;
632 printf( "OnEnter from " );
633 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
634 printf( win->GetClassInfo()->GetClassName() );
638 if ((widget
->window
) && (win
->m_cursor
))
639 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
641 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
642 event
.SetEventObject( win
);
644 if (win
->GetEventHandler()->ProcessEvent( event
))
645 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
650 //-----------------------------------------------------------------------------
651 // "leave_notify_event"
652 //-----------------------------------------------------------------------------
654 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
656 if (widget
->window
!= gdk_event
->window
) return TRUE
;
658 if (g_blockEventsOnDrag
) return TRUE
;
660 if (!win
->HasVMT()) return TRUE
;
663 printf( "OnLeave from " );
664 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
665 printf( win->GetClassInfo()->GetClassName() );
669 if ((widget
->window
) && (win
->m_cursor
))
670 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
672 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
673 event
.SetEventObject( win
);
675 if (win
->GetEventHandler()->ProcessEvent( event
))
676 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
681 //-----------------------------------------------------------------------------
682 // "value_changed" from m_vAdjust
683 //-----------------------------------------------------------------------------
685 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
687 if (g_blockEventsOnDrag
) return;
690 printf( "OnVScroll from " );
691 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
692 printf( win->GetClassInfo()->GetClassName() );
696 if (!win
->HasVMT()) return;
698 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
699 if (fabs(diff
) < 0.2) return;
701 wxEventType command
= wxEVT_NULL
;
703 float line_step
= win
->m_vAdjust
->step_increment
;
704 float page_step
= win
->m_vAdjust
->page_increment
;
706 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
707 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
708 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
709 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
710 else command
= wxEVT_SCROLL_THUMBTRACK
;
712 int value
= (int)(win
->m_vAdjust
->value
+0.5);
714 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
715 event
.SetEventObject( win
);
716 win
->GetEventHandler()->ProcessEvent( event
);
719 //-----------------------------------------------------------------------------
720 // "value_changed" from m_hAdjust
721 //-----------------------------------------------------------------------------
723 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
725 if (g_blockEventsOnDrag
) return;
728 printf( "OnHScroll from " );
729 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
730 printf( win->GetClassInfo()->GetClassName() );
734 if (!win
->HasVMT()) return;
736 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
737 if (fabs(diff
) < 0.2) return;
739 wxEventType command
= wxEVT_NULL
;
741 float line_step
= win
->m_hAdjust
->step_increment
;
742 float page_step
= win
->m_hAdjust
->page_increment
;
744 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
745 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
746 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
747 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
748 else command
= wxEVT_SCROLL_THUMBTRACK
;
750 int value
= (int)(win
->m_hAdjust
->value
+0.5);
752 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
753 event
.SetEventObject( win
);
754 win
->GetEventHandler()->ProcessEvent( event
);
757 //-----------------------------------------------------------------------------
758 // "changed" from m_vAdjust
759 //-----------------------------------------------------------------------------
761 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
763 if (g_blockEventsOnDrag
) return;
766 printf( "OnVScroll change from " );
767 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
768 printf( win->GetClassInfo()->GetClassName() );
772 if (!win
->HasVMT()) return;
774 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
775 int value
= (int)(win
->m_vAdjust
->value
+0.5);
777 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
778 event
.SetEventObject( win
);
779 win
->GetEventHandler()->ProcessEvent( event
);
782 //-----------------------------------------------------------------------------
783 // "changed" from m_hAdjust
784 //-----------------------------------------------------------------------------
786 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
788 if (g_blockEventsOnDrag
) return;
791 printf( "OnHScroll change from " );
792 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
793 printf( win->GetClassInfo()->GetClassName() );
797 if (!win
->HasVMT()) return;
799 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
800 int value
= (int)(win
->m_hAdjust
->value
+0.5);
802 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
803 event
.SetEventObject( win
);
804 win
->GetEventHandler()->ProcessEvent( event
);
807 //-----------------------------------------------------------------------------
808 // "button_press_event" from scrollbar
809 //-----------------------------------------------------------------------------
811 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
813 if (gdk_event
->window
!= widget
->slider
) return FALSE
;
815 win
->m_isScrolling
= TRUE
;
820 //-----------------------------------------------------------------------------
821 // "button_release_event" from scrollbar
822 //-----------------------------------------------------------------------------
824 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
826 if (gdk_event
->window
!= widget
->slider
) return FALSE
;
828 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(win
->m_widget
);
830 if (widget
== GTK_RANGE(s_window
->vscrollbar
))
831 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
833 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
835 win
->m_isScrolling
= FALSE
;
840 //-----------------------------------------------------------------------------
841 // "drop_data_available_event"
842 //-----------------------------------------------------------------------------
844 static void gtk_window_drop_callback( GtkWidget
*widget
, GdkEvent
*event
, wxWindow
*win
)
846 if (!win
->HasVMT()) return;
848 if (win
->GetDropTarget())
852 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
853 win
->GetDropTarget()->Drop( event
, x
, y
);
857 g_free (event->dropdataavailable.data);
858 g_free (event->dropdataavailable.data_type);
862 //-----------------------------------------------------------------------------
864 //-----------------------------------------------------------------------------
866 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
868 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
869 EVT_SIZE(wxWindow::OnSize
)
870 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
871 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
872 EVT_IDLE(wxWindow::OnIdle
)
877 m_widget
= (GtkWidget
*) NULL
;
878 m_wxwindow
= (GtkWidget
*) NULL
;
879 m_parent
= (wxWindow
*) NULL
;
880 m_children
.DeleteContents( FALSE
);
890 m_eventHandler
= this;
891 m_windowValidator
= (wxValidator
*) NULL
;
893 m_cursor
= (wxCursor
*) NULL
;
894 m_font
= *wxSWISS_FONT
;
896 m_windowName
= "noname";
897 m_constraints
= (wxLayoutConstraints
*) NULL
;
898 m_constraintsInvolvedIn
= (wxList
*) NULL
;
899 m_windowSizer
= (wxSizer
*) NULL
;
900 m_sizerParent
= (wxWindow
*) NULL
;
901 m_autoLayout
= FALSE
;
905 m_hasScrolling
= FALSE
;
906 m_isScrolling
= FALSE
;
907 m_hAdjust
= (GtkAdjustment
*) NULL
;
908 m_vAdjust
= (GtkAdjustment
*) NULL
;
909 m_oldHorizontalPos
= 0.0;
910 m_oldVerticalPos
= 0.0;
913 m_pDropTarget
= (wxDropTarget
*) NULL
;
915 m_hasOwnStyle
= FALSE
;
916 m_scrollGC
= (GdkGC
*) NULL
;
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 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()
1028 if (m_pDropTarget
) delete m_pDropTarget
;
1030 if (m_parent
) m_parent
->RemoveChild( this );
1031 if (m_widget
) Show( FALSE
);
1035 if (m_scrollGC
) gdk_gc_unref( m_scrollGC
);
1037 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
1039 if (m_widget
) gtk_widget_destroy( m_widget
);
1043 DeleteRelatedConstraints();
1046 // This removes any dangling pointers to this window
1047 // in other windows' constraintsInvolvedIn lists.
1048 UnsetConstraints(m_constraints
);
1049 delete m_constraints
;
1050 m_constraints
= (wxLayoutConstraints
*) NULL
;
1054 delete m_windowSizer
;
1055 m_windowSizer
= (wxSizer
*) NULL
;
1057 // If this is a child of a sizer, remove self from parent
1058 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
1060 // Just in case the window has been Closed, but
1061 // we're then deleting immediately: don't leave
1062 // dangling pointers.
1063 wxPendingDelete
.DeleteObject(this);
1065 // Just in case we've loaded a top-level window via
1066 // wxWindow::LoadNativeDialog but we weren't a dialog
1068 wxTopLevelWindows
.DeleteObject(this);
1070 if (m_windowValidator
) delete m_windowValidator
;
1073 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1074 const wxPoint
&pos
, const wxSize
&size
,
1075 long style
, const wxString
&name
)
1077 if (m_needParent
&& (parent
== NULL
))
1078 wxFatalError( "Need complete parent.", name
);
1080 m_widget
= (GtkWidget
*) NULL
;
1083 m_children
.DeleteContents( FALSE
);
1087 if (m_width
== -1) m_width
= 20;
1089 if (m_height
== -1) m_height
= 20;
1095 m_eventHandler
= this;
1098 if (m_cursor
== NULL
)
1099 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1100 m_font
= *wxSWISS_FONT
;
1101 // m_backgroundColour = wxWHITE;
1102 m_foregroundColour
= wxBLACK
;
1103 m_windowStyle
= style
;
1104 m_windowName
= name
;
1105 m_constraints
= (wxLayoutConstraints
*) NULL
;
1106 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1107 m_windowSizer
= (wxSizer
*) NULL
;
1108 m_sizerParent
= (wxWindow
*) NULL
;
1109 m_autoLayout
= FALSE
;
1110 m_hasScrolling
= FALSE
;
1111 m_isScrolling
= FALSE
;
1112 m_pDropTarget
= (wxDropTarget
*) NULL
;
1114 m_windowValidator
= (wxValidator
*) NULL
;
1115 m_hasOwnStyle
= FALSE
;
1116 m_scrollGC
= (GdkGC
*) NULL
;
1119 void wxWindow::PostCreation()
1121 if (m_parent
) m_parent
->AddChild( this );
1125 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1126 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1128 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1129 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1132 ConnectWidget( GetConnectWidget() );
1134 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1136 if (m_wxwindow
) gtk_widget_realize( m_wxwindow
);
1138 SetCursor( *wxSTANDARD_CURSOR
);
1143 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1145 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1146 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1148 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1149 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1151 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1152 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1154 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1155 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1157 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1158 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1160 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1161 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1163 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1164 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1166 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1167 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1170 bool wxWindow::HasVMT()
1175 bool wxWindow::Close( bool force
)
1177 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1179 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1180 event
.SetEventObject(this);
1181 event
.SetForce(force
);
1183 return GetEventHandler()->ProcessEvent(event
);
1186 bool wxWindow::Destroy()
1188 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1195 bool wxWindow::DestroyChildren()
1200 while ((node
= GetChildren()->First()) != (wxNode
*)NULL
)
1203 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1206 if (GetChildren()->Member(child
)) delete node
;
1213 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1215 // are we to set fonts here ?
1218 void wxWindow::ImplementSetSize()
1220 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1221 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1222 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_minWidth
;
1223 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_minHeight
;
1224 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1227 void wxWindow::ImplementSetPosition()
1229 if (IS_KIND_OF(this,wxFrame
) || IS_KIND_OF(this,wxDialog
))
1231 if ((m_x
!= -1) || (m_y
!= -1))
1232 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
1238 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1242 if ((m_parent
) && (m_parent
->m_wxwindow
))
1243 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
, m_y
);
1245 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1248 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1250 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1252 if (m_resizing
) return; // I don't like recursions
1260 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1262 if (newX
== -1) newX
= m_x
;
1263 if (newY
== -1) newY
= m_y
;
1264 if (newW
== -1) newW
= m_width
;
1265 if (newH
== -1) newH
= m_height
;
1268 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1270 if (newW
== -1) newW
= 80;
1273 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1275 if (newH
== -1) newH
= 26;
1278 if ((m_x
!= newX
) || (m_y
!= newY
) || (!m_sizeSet
))
1282 ImplementSetPosition();
1284 if ((m_width
!= newW
) || (m_height
!= newH
) || (!m_sizeSet
))
1292 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1293 event
.SetEventObject( this );
1294 ProcessEvent( event
);
1299 void wxWindow::SetSize( int width
, int height
)
1301 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1304 void wxWindow::Move( int x
, int y
)
1306 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1309 void wxWindow::GetSize( int *width
, int *height
) const
1311 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1313 if (width
) (*width
) = m_width
;
1314 if (height
) (*height
) = m_height
;
1317 void wxWindow::SetClientSize( int width
, int height
)
1319 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1323 SetSize( width
, height
);
1330 if (!m_hasScrolling
)
1333 do we have sunken dialogs ?
1335 GtkStyleClass *window_class = m_wxwindow->style->klass;
1337 dw += 2 * window_class->xthickness;
1338 dh += 2 * window_class->ythickness;
1343 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1344 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1346 GtkWidget
*viewport
= scroll_window
->viewport
;
1347 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1349 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1350 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1352 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1353 (m_windowStyle
& wxSUNKEN_BORDER
))
1355 dw
+= 2 * viewport_class
->xthickness
;
1356 dh
+= 2 * viewport_class
->ythickness
;
1359 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1361 dw
+= vscrollbar
->allocation
.width
;
1362 dw
+= scroll_class
->scrollbar_spacing
;
1365 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1367 dh
+= hscrollbar
->allocation
.height
;
1368 dw
+= scroll_class
->scrollbar_spacing
;
1372 SetSize( width
+dw
, height
+dh
);
1376 void wxWindow::GetClientSize( int *width
, int *height
) const
1378 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1382 if (width
) (*width
) = m_width
;
1383 if (height
) (*height
) = m_height
;
1390 if (!m_hasScrolling
)
1393 do we have sunken dialogs ?
1395 GtkStyleClass *window_class = m_wxwindow->style->klass;
1397 dw += 2 * window_class->xthickness;
1398 dh += 2 * window_class->ythickness;
1403 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1404 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1406 GtkWidget
*viewport
= scroll_window
->viewport
;
1407 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1409 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1410 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1412 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1413 (m_windowStyle
& wxSUNKEN_BORDER
))
1415 dw
+= 2 * viewport_class
->xthickness
;
1416 dh
+= 2 * viewport_class
->ythickness
;
1419 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1421 // dw += vscrollbar->allocation.width;
1422 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1423 dw
+= scroll_class
->scrollbar_spacing
;
1426 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1428 // dh += hscrollbar->allocation.height;
1430 dh
+= scroll_class
->scrollbar_spacing
;
1434 if (width
) (*width
) = m_width
- dw
;
1435 if (height
) (*height
) = m_height
- dh
;
1439 void wxWindow::GetPosition( int *x
, int *y
) const
1441 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1447 void wxWindow::ClientToScreen( int *x
, int *y
)
1449 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1451 GdkWindow
*source
= (GdkWindow
*) NULL
;
1453 source
= m_wxwindow
->window
;
1455 source
= m_widget
->window
;
1459 gdk_window_get_origin( source
, &org_x
, &org_y
);
1463 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1465 org_x
+= m_widget
->allocation
.x
;
1466 org_y
+= m_widget
->allocation
.y
;
1474 void wxWindow::ScreenToClient( int *x
, int *y
)
1476 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1478 GdkWindow
*source
= (GdkWindow
*) NULL
;
1480 source
= m_wxwindow
->window
;
1482 source
= m_widget
->window
;
1486 gdk_window_get_origin( source
, &org_x
, &org_y
);
1490 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1492 org_x
+= m_widget
->allocation
.x
;
1493 org_y
+= m_widget
->allocation
.y
;
1501 void wxWindow::Centre( int direction
)
1503 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1505 if (IS_KIND_OF(this,wxDialog
) || IS_KIND_OF(this,wxFrame
))
1507 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (gdk_screen_width () - m_width
) / 2;
1508 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (gdk_screen_height () - m_height
) / 2;
1509 ImplementSetPosition();
1517 m_parent
->GetSize( &p_w
, &p_h
);
1518 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (p_w
- m_width
) / 2;
1519 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (p_h
- m_height
) / 2;
1520 ImplementSetPosition();
1525 void wxWindow::Fit()
1527 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1531 wxNode
*node
= GetChildren()->First();
1534 wxWindow
*win
= (wxWindow
*)node
->Data();
1536 win
->GetPosition(&wx
, &wy
);
1537 win
->GetSize(&ww
, &wh
);
1538 if ( wx
+ ww
> maxX
)
1540 if ( wy
+ wh
> maxY
)
1543 node
= node
->Next();
1545 SetClientSize(maxX
+ 5, maxY
+ 10);
1548 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1550 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1558 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1560 //if (GetAutoLayout()) Layout();
1563 bool wxWindow::Show( bool show
)
1565 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1568 gtk_widget_show( m_widget
);
1570 gtk_widget_hide( m_widget
);
1575 void wxWindow::Enable( bool enable
)
1577 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1579 m_isEnabled
= enable
;
1580 gtk_widget_set_sensitive( m_widget
, enable
);
1581 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1584 int wxWindow::GetCharHeight() const
1586 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1590 wxFAIL_MSG( "invalid font" );
1594 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1595 return font
->ascent
+ font
->descent
;
1598 int wxWindow::GetCharWidth() const
1600 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1604 wxFAIL_MSG( "invalid font" );
1608 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1609 return gdk_string_width( font
, "H" );
1612 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1613 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1615 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1617 wxFont fontToUse
= m_font
;
1618 if (theFont
) fontToUse
= *theFont
;
1620 if (!fontToUse
.Ok())
1622 wxFAIL_MSG( "invalid font" );
1625 wxASSERT_MSG( (m_font
.Ok()), "invalid font" );
1627 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1628 if (x
) (*x
) = gdk_string_width( font
, string
);
1629 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1630 if (descent
) (*descent
) = font
->descent
;
1631 if (externalLeading
) (*externalLeading
) = 0; // ??
1634 void wxWindow::MakeModal( bool modal
)
1637 // Disable all other windows
1638 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1640 wxNode
*node
= wxTopLevelWindows
.First();
1643 wxWindow
*win
= (wxWindow
*)node
->Data();
1645 win
->Enable(!modal
);
1647 node
= node
->Next();
1652 void wxWindow::SetFocus()
1654 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1656 GtkWidget
*connect_widget
= GetConnectWidget();
1659 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) && !GTK_WIDGET_HAS_FOCUS (connect_widget
) )
1661 gtk_widget_grab_focus (connect_widget
);
1666 bool wxWindow::OnClose()
1671 void wxWindow::AddChild( wxWindow
*child
)
1673 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1674 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window need client area" );
1675 wxASSERT_MSG( (child
!= NULL
), "invalid child" );
1676 wxASSERT_MSG( (child
->m_widget
!= NULL
), "invalid child" );
1678 // Addchild is (often) called before the program
1679 // has left the parents constructor so that no
1680 // virtual tables work yet. The approach below
1681 // practically imitates virtual tables, i.e. it
1682 // implements a different AddChild() behaviour
1683 // for wxFrame, wxDialog, wxWindow and
1684 // wxMDIParentFrame.
1686 // wxFrame and wxDialog as children aren't placed into the parents
1688 if (( IS_KIND_OF(child
,wxFrame
) || IS_KIND_OF(child
,wxDialog
) ) &&
1689 (!IS_KIND_OF(child
,wxMDIChildFrame
)))
1691 m_children
.Append( child
);
1693 if ((child
->m_x
!= -1) && (child
->m_y
!= -1))
1694 gtk_widget_set_uposition( child
->m_widget
, child
->m_x
, child
->m_y
);
1699 // In the case of an wxMDIChildFrame descendant, we use the
1700 // client windows's AddChild()
1702 if (IS_KIND_OF(this,wxMDIParentFrame
))
1704 if (IS_KIND_OF(child
,wxMDIChildFrame
))
1706 wxMDIClientWindow
*client
= ((wxMDIParentFrame
*)this)->GetClientWindow();
1709 client
->AddChild( child
);
1715 // wxNotebook is very special, so it has a private AddChild()
1717 if (IS_KIND_OF(this,wxNotebook
))
1719 wxNotebook
*tab
= (wxNotebook
*)this;
1720 tab
->AddChild( child
);
1724 // wxFrame has a private AddChild
1726 if (IS_KIND_OF(this,wxFrame
) && !IS_KIND_OF(this,wxMDIChildFrame
))
1728 wxFrame
*frame
= (wxFrame
*)this;
1729 frame
->AddChild( child
);
1735 m_children
.Append( child
);
1736 if (m_wxwindow
) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), child
->m_widget
,
1737 child
->m_x
, child
->m_y
);
1739 gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height
);
1742 wxList
*wxWindow::GetChildren()
1744 return (&m_children
);
1747 void wxWindow::RemoveChild( wxWindow
*child
)
1750 GetChildren()->DeleteObject( child
);
1751 child
->m_parent
= (wxWindow
*) NULL
;
1754 void wxWindow::SetReturnCode( int retCode
)
1756 m_retCode
= retCode
;
1759 int wxWindow::GetReturnCode()
1764 void wxWindow::Raise()
1766 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1768 if (m_widget
) gdk_window_raise( m_widget
->window
);
1771 void wxWindow::Lower()
1773 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1775 if (m_widget
) gdk_window_lower( m_widget
->window
);
1778 wxEvtHandler
*wxWindow::GetEventHandler()
1780 return m_eventHandler
;
1783 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
1785 m_eventHandler
= handler
;
1788 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
1790 handler
->SetNextHandler(GetEventHandler());
1791 SetEventHandler(handler
);
1794 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
1796 if (GetEventHandler())
1798 wxEvtHandler
*handlerA
= GetEventHandler();
1799 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
1800 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
1801 SetEventHandler(handlerB
);
1805 return (wxEvtHandler
*) NULL
;
1811 return (wxEvtHandler
*) NULL
;
1814 wxValidator
*wxWindow::GetValidator()
1816 return m_windowValidator
;
1819 void wxWindow::SetValidator( const wxValidator
& validator
)
1821 if (m_windowValidator
) delete m_windowValidator
;
1822 m_windowValidator
= validator
.Clone();
1823 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
1826 bool wxWindow::IsBeingDeleted()
1831 void wxWindow::SetId( wxWindowID id
)
1836 wxWindowID
wxWindow::GetId()
1841 void wxWindow::SetCursor( const wxCursor
&cursor
)
1843 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1845 if (m_cursor
== NULL
)
1847 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1848 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1853 if (*((wxCursor
*)&cursor
) == m_cursor
) return;
1858 *m_cursor
= *wxSTANDARD_CURSOR
;
1861 if ((m_widget
) && (m_widget
->window
))
1862 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
1864 if ((m_wxwindow
) && (m_wxwindow
->window
))
1865 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
1868 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
1870 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1872 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
1875 gdk_window_clear_area( m_wxwindow
->window
,
1889 GetClientSize( &w
, &h
);
1891 GdkRectangle gdk_rect
;
1895 gdk_rect
.height
= h
;
1896 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1901 GdkRectangle gdk_rect
;
1902 gdk_rect
.x
= rect
->x
;
1903 gdk_rect
.y
= rect
->y
;
1904 gdk_rect
.width
= rect
->width
;
1905 gdk_rect
.height
= rect
->height
;
1908 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1910 gtk_widget_draw( m_widget
, &gdk_rect
);
1914 wxRegion
wxWindow::GetUpdateRegion() const
1916 return m_updateRegion
;
1919 bool wxWindow::IsExposed( int x
, int y
) const
1921 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
1924 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
1926 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
1929 bool wxWindow::IsExposed( const wxPoint
& pt
) const
1931 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
1934 bool wxWindow::IsExposed( const wxRect
& rect
) const
1936 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
1939 void wxWindow::Clear()
1941 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
1943 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
1946 wxColour
wxWindow::GetBackgroundColour() const
1948 return m_backgroundColour
;
1951 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
1953 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
1955 m_backgroundColour
= colour
;
1956 if (!m_backgroundColour
.Ok()) return;
1960 GdkWindow
*window
= m_wxwindow
->window
;
1961 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
1962 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
1963 gdk_window_clear( window
);
1967 GtkStyle
*style
= gtk_widget_get_style( m_widget
);
1970 m_hasOwnStyle
= TRUE
;
1971 style
= gtk_style_copy( style
);
1974 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
1975 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
1976 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
1978 gtk_widget_set_style( m_widget
, style
);
1982 wxColour
wxWindow::GetForegroundColour() const
1984 return m_foregroundColour
;
1987 void wxWindow::SetForegroundColour( const wxColour
&colour
)
1989 m_foregroundColour
= colour
;
1992 bool wxWindow::Validate()
1994 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
1996 wxNode
*node
= GetChildren()->First();
1999 wxWindow
*child
= (wxWindow
*)node
->Data();
2000 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
2002 node
= node
->Next();
2007 bool wxWindow::TransferDataToWindow()
2009 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2011 wxNode
*node
= GetChildren()->First();
2014 wxWindow
*child
= (wxWindow
*)node
->Data();
2015 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
2016 !child
->GetValidator()->TransferToWindow() )
2018 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
2021 node
= node
->Next();
2026 bool wxWindow::TransferDataFromWindow()
2028 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2030 wxNode
*node
= GetChildren()->First();
2033 wxWindow
*child
= (wxWindow
*)node
->Data();
2034 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
2036 node
= node
->Next();
2041 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
2043 m_acceleratorTable
= accel
;
2046 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
2048 TransferDataToWindow();
2051 void wxWindow::InitDialog()
2053 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2055 wxInitDialogEvent
event(GetId());
2056 event
.SetEventObject( this );
2057 GetEventHandler()->ProcessEvent(event
);
2060 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2062 menu
->SetInvokingWindow( win
);
2063 wxNode
*node
= menu
->m_items
.First();
2066 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2067 if (menuitem
->IsSubMenu())
2068 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2069 node
= node
->Next();
2073 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
2075 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2077 SetInvokingWindow( menu
, this );
2079 GTK_MENU(menu
->m_menu
),
2080 (GtkWidget
*)NULL
, // parent menu shell
2081 (GtkWidget
*)NULL
, // parent menu item
2082 (GtkMenuPositionFunc
)NULL
,
2083 NULL
, // client data
2084 0, // button used to activate it
2085 0//gs_timeLastClick // the time of activation
2090 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2092 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2094 GtkWidget
*dnd_widget
= GetConnectWidget();
2096 DisconnectDnDWidget( dnd_widget
);
2098 if (m_pDropTarget
) delete m_pDropTarget
;
2099 m_pDropTarget
= dropTarget
;
2101 ConnectDnDWidget( dnd_widget
);
2104 wxDropTarget
*wxWindow::GetDropTarget() const
2106 return m_pDropTarget
;
2109 void wxWindow::ConnectDnDWidget( GtkWidget
*widget
)
2111 if (!m_pDropTarget
) return;
2113 m_pDropTarget
->RegisterWidget( widget
);
2115 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
2116 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2119 void wxWindow::DisconnectDnDWidget( GtkWidget
*widget
)
2121 if (!m_pDropTarget
) return;
2123 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
2124 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2126 m_pDropTarget
->UnregisterWidget( widget
);
2129 GtkWidget
* wxWindow::GetConnectWidget()
2131 GtkWidget
*connect_widget
= m_widget
;
2132 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2134 return connect_widget
;
2137 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2139 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2140 return (window
== m_widget
->window
);
2143 void wxWindow::SetFont( const wxFont
&font
)
2145 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2147 if (((wxFont
*)&font
)->Ok())
2150 m_font
= *wxSWISS_FONT
;
2152 GtkStyle
*style
= gtk_widget_get_style( m_widget
);
2155 m_hasOwnStyle
= TRUE
;
2156 style
= gtk_style_copy( style
);
2159 gdk_font_unref( style
->font
);
2160 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2162 gtk_widget_set_style( m_widget
, style
);
2165 wxFont
*wxWindow::GetFont()
2170 void wxWindow::SetWindowStyleFlag( long flag
)
2172 m_windowStyle
= flag
;
2175 long wxWindow::GetWindowStyleFlag() const
2177 return m_windowStyle
;
2180 void wxWindow::CaptureMouse()
2182 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2184 wxASSERT_MSG( (g_capturing
== FALSE
), "CaptureMouse called twice" );
2186 GtkWidget
*connect_widget
= GetConnectWidget();
2187 gtk_grab_add( connect_widget
);
2188 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
2190 (GDK_BUTTON_PRESS_MASK
|
2191 GDK_BUTTON_RELEASE_MASK
|
2192 GDK_POINTER_MOTION_MASK
),
2193 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
2197 void wxWindow::ReleaseMouse()
2199 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2201 wxASSERT_MSG( (g_capturing
== TRUE
), "ReleaseMouse called twice" );
2203 GtkWidget
*connect_widget
= GetConnectWidget();
2204 gtk_grab_remove( connect_widget
);
2205 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2206 g_capturing
= FALSE
;
2209 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2213 wxString
wxWindow::GetTitle() const
2215 return (wxString
&)m_windowName
;
2218 wxString
wxWindow::GetLabel() const
2223 void wxWindow::SetName( const wxString
&name
)
2225 m_windowName
= name
;
2228 wxString
wxWindow::GetName() const
2230 return (wxString
&)m_windowName
;
2233 bool wxWindow::IsShown() const
2238 bool wxWindow::IsRetained()
2243 wxWindow
*wxWindow::FindWindow( long id
)
2245 if (id
== m_windowId
) return this;
2246 wxNode
*node
= m_children
.First();
2249 wxWindow
*child
= (wxWindow
*)node
->Data();
2250 wxWindow
*res
= child
->FindWindow( id
);
2251 if (res
) return res
;
2252 node
= node
->Next();
2254 return (wxWindow
*) NULL
;
2257 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2259 if (name
== m_windowName
) return this;
2260 wxNode
*node
= m_children
.First();
2263 wxWindow
*child
= (wxWindow
*)node
->Data();
2264 wxWindow
*res
= child
->FindWindow( name
);
2265 if (res
) return res
;
2266 node
= node
->Next();
2268 return (wxWindow
*) NULL
;
2271 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2272 int range
, bool refresh
)
2274 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2276 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2278 if (!m_wxwindow
) return;
2280 if (orient
== wxHORIZONTAL
)
2282 float fpos
= (float)pos
;
2283 float frange
= (float)range
;
2284 float fthumb
= (float)thumbVisible
;
2286 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2287 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2289 SetScrollPos( orient
, pos
, refresh
);
2293 m_oldHorizontalPos
= fpos
;
2295 m_hAdjust
->lower
= 0.0;
2296 m_hAdjust
->upper
= frange
;
2297 m_hAdjust
->value
= fpos
;
2298 m_hAdjust
->step_increment
= 1.0;
2299 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2300 m_hAdjust
->page_size
= fthumb
;
2304 float fpos
= (float)pos
;
2305 float frange
= (float)range
;
2306 float fthumb
= (float)thumbVisible
;
2308 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2309 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2311 SetScrollPos( orient
, pos
, refresh
);
2315 m_oldVerticalPos
= fpos
;
2317 m_vAdjust
->lower
= 0.0;
2318 m_vAdjust
->upper
= frange
;
2319 m_vAdjust
->value
= fpos
;
2320 m_vAdjust
->step_increment
= 1.0;
2321 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2322 m_vAdjust
->page_size
= fthumb
;
2325 if (m_wxwindow
->window
)
2327 if (orient
== wxHORIZONTAL
)
2328 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2330 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2332 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2336 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2338 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2340 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2342 if (!m_wxwindow
) return;
2344 if (orient
== wxHORIZONTAL
)
2346 float fpos
= (float)pos
;
2347 m_oldHorizontalPos
= fpos
;
2349 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2350 m_hAdjust
->value
= fpos
;
2354 float fpos
= (float)pos
;
2355 m_oldVerticalPos
= fpos
;
2356 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2357 m_vAdjust
->value
= fpos
;
2362 if (m_wxwindow
->window
)
2364 if (orient
== wxHORIZONTAL
)
2365 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2367 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2372 int wxWindow::GetScrollThumb( int orient
) const
2374 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2376 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2378 if (!m_wxwindow
) return 0;
2380 if (orient
== wxHORIZONTAL
)
2381 return (int)(m_hAdjust
->page_size
+0.5);
2383 return (int)(m_vAdjust
->page_size
+0.5);
2386 int wxWindow::GetScrollPos( int orient
) const
2388 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2390 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2392 if (!m_wxwindow
) return 0;
2394 if (orient
== wxHORIZONTAL
)
2395 return (int)(m_hAdjust
->value
+0.5);
2397 return (int)(m_vAdjust
->value
+0.5);
2400 int wxWindow::GetScrollRange( int orient
) const
2402 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2404 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2406 if (!m_wxwindow
) return 0;
2408 if (orient
== wxHORIZONTAL
)
2409 return (int)(m_hAdjust
->upper
+0.5);
2411 return (int)(m_vAdjust
->upper
+0.5);
2414 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2416 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2418 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2420 if (!m_wxwindow
) return;
2424 GetClientSize( &cw
, &ch
);
2426 int w
= cw
- abs(dx
);
2427 int h
= ch
- abs(dy
);
2428 if ((h
< 0) || (w
< 0))
2435 if (dx
< 0) s_x
= -dx
;
2436 if (dy
< 0) s_y
= -dy
;
2439 if (dx
> 0) d_x
= dx
;
2440 if (dy
> 0) d_y
= dy
;
2444 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2445 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2448 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2449 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2452 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2453 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2454 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2455 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2457 Refresh( TRUE
, &rect
);
2460 //-------------------------------------------------------------------------------------
2462 //-------------------------------------------------------------------------------------
2464 wxLayoutConstraints
*wxWindow::GetConstraints() const
2466 return m_constraints
;
2469 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2473 UnsetConstraints(m_constraints
);
2474 delete m_constraints
;
2476 m_constraints
= constraints
;
2479 // Make sure other windows know they're part of a 'meaningful relationship'
2480 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2481 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2482 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2483 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2484 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2485 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2486 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2487 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2488 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2489 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2490 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2491 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2492 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2493 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2494 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2495 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2501 void wxWindow::SetAutoLayout( bool autoLayout
)
2503 m_autoLayout
= autoLayout
;
2506 bool wxWindow::GetAutoLayout() const
2508 return m_autoLayout
;
2511 wxSizer
*wxWindow::GetSizer() const
2513 return m_windowSizer
;
2516 void wxWindow::SetSizerParent( wxWindow
*win
)
2518 m_sizerParent
= win
;
2521 wxWindow
*wxWindow::GetSizerParent() const
2523 return m_sizerParent
;
2526 // This removes any dangling pointers to this window
2527 // in other windows' constraintsInvolvedIn lists.
2528 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2532 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2533 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2534 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2535 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2536 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2537 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2538 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2539 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2540 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2541 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2542 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2543 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2544 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2545 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2546 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2547 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2551 // Back-pointer to other windows we're involved with, so if we delete
2552 // this window, we must delete any constraints we're involved with.
2553 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2555 if (!m_constraintsInvolvedIn
)
2556 m_constraintsInvolvedIn
= new wxList
;
2557 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2558 m_constraintsInvolvedIn
->Append(otherWin
);
2561 // REMOVE back-pointer to other windows we're involved with.
2562 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2564 if (m_constraintsInvolvedIn
)
2565 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2568 // Reset any constraints that mention this window
2569 void wxWindow::DeleteRelatedConstraints()
2571 if (m_constraintsInvolvedIn
)
2573 wxNode
*node
= m_constraintsInvolvedIn
->First();
2576 wxWindow
*win
= (wxWindow
*)node
->Data();
2577 wxNode
*next
= node
->Next();
2578 wxLayoutConstraints
*constr
= win
->GetConstraints();
2580 // Reset any constraints involving this window
2583 constr
->left
.ResetIfWin((wxWindow
*)this);
2584 constr
->top
.ResetIfWin((wxWindow
*)this);
2585 constr
->right
.ResetIfWin((wxWindow
*)this);
2586 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2587 constr
->width
.ResetIfWin((wxWindow
*)this);
2588 constr
->height
.ResetIfWin((wxWindow
*)this);
2589 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2590 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2595 delete m_constraintsInvolvedIn
;
2596 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2600 void wxWindow::SetSizer(wxSizer
*sizer
)
2602 m_windowSizer
= sizer
;
2604 sizer
->SetSizerParent((wxWindow
*)this);
2611 bool wxWindow::Layout()
2613 if (GetConstraints())
2616 GetClientSize(&w
, &h
);
2617 GetConstraints()->width
.SetValue(w
);
2618 GetConstraints()->height
.SetValue(h
);
2621 // If top level (one sizer), evaluate the sizer's constraints.
2625 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2626 GetSizer()->LayoutPhase1(&noChanges
);
2627 GetSizer()->LayoutPhase2(&noChanges
);
2628 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2633 // Otherwise, evaluate child constraints
2634 ResetConstraints(); // Mark all constraints as unevaluated
2635 DoPhase(1); // Just one phase need if no sizers involved
2637 SetConstraintSizes(); // Recursively set the real window sizes
2643 // Do a phase of evaluating constraints:
2644 // the default behaviour. wxSizers may do a similar
2645 // thing, but also impose their own 'constraints'
2646 // and order the evaluation differently.
2647 bool wxWindow::LayoutPhase1(int *noChanges
)
2649 wxLayoutConstraints
*constr
= GetConstraints();
2652 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2658 bool wxWindow::LayoutPhase2(int *noChanges
)
2668 // Do a phase of evaluating child constraints
2669 bool wxWindow::DoPhase(int phase
)
2671 int noIterations
= 0;
2672 int maxIterations
= 500;
2676 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2680 wxNode
*node
= GetChildren()->First();
2683 wxWindow
*child
= (wxWindow
*)node
->Data();
2684 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2686 wxLayoutConstraints
*constr
= child
->GetConstraints();
2689 if (succeeded
.Member(child
))
2694 int tempNoChanges
= 0;
2695 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2696 noChanges
+= tempNoChanges
;
2699 succeeded
.Append(child
);
2704 node
= node
->Next();
2711 void wxWindow::ResetConstraints()
2713 wxLayoutConstraints
*constr
= GetConstraints();
2716 constr
->left
.SetDone(FALSE
);
2717 constr
->top
.SetDone(FALSE
);
2718 constr
->right
.SetDone(FALSE
);
2719 constr
->bottom
.SetDone(FALSE
);
2720 constr
->width
.SetDone(FALSE
);
2721 constr
->height
.SetDone(FALSE
);
2722 constr
->centreX
.SetDone(FALSE
);
2723 constr
->centreY
.SetDone(FALSE
);
2725 wxNode
*node
= GetChildren()->First();
2728 wxWindow
*win
= (wxWindow
*)node
->Data();
2729 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2730 win
->ResetConstraints();
2731 node
= node
->Next();
2735 // Need to distinguish between setting the 'fake' size for
2736 // windows and sizers, and setting the real values.
2737 void wxWindow::SetConstraintSizes(bool recurse
)
2739 wxLayoutConstraints
*constr
= GetConstraints();
2740 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2741 constr
->width
.GetDone() && constr
->height
.GetDone())
2743 int x
= constr
->left
.GetValue();
2744 int y
= constr
->top
.GetValue();
2745 int w
= constr
->width
.GetValue();
2746 int h
= constr
->height
.GetValue();
2748 // If we don't want to resize this window, just move it...
2749 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2750 (constr
->height
.GetRelationship() != wxAsIs
))
2752 // Calls Layout() recursively. AAAGH. How can we stop that.
2753 // Simply take Layout() out of non-top level OnSizes.
2754 SizerSetSize(x
, y
, w
, h
);
2763 char *windowClass
= this->GetClassInfo()->GetClassName();
2766 if (GetName() == "")
2767 winName
= _("unnamed");
2769 winName
= GetName();
2770 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2771 if (!constr
->left
.GetDone())
2772 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2773 if (!constr
->right
.GetDone())
2774 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2775 if (!constr
->width
.GetDone())
2776 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2777 if (!constr
->height
.GetDone())
2778 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2779 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2784 wxNode
*node
= GetChildren()->First();
2787 wxWindow
*win
= (wxWindow
*)node
->Data();
2788 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2789 win
->SetConstraintSizes();
2790 node
= node
->Next();
2795 // This assumes that all sizers are 'on' the same
2796 // window, i.e. the parent of this window.
2797 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2799 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2800 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2804 m_sizerParent
->GetPosition(&xp
, &yp
);
2805 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2810 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2814 TransformSizerToActual(&xx
, &yy
);
2815 SetSize(xx
, yy
, w
, h
);
2818 void wxWindow::SizerMove(int x
, int y
)
2822 TransformSizerToActual(&xx
, &yy
);
2826 // Only set the size/position of the constraint (if any)
2827 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2829 wxLayoutConstraints
*constr
= GetConstraints();
2834 constr
->left
.SetValue(x
);
2835 constr
->left
.SetDone(TRUE
);
2839 constr
->top
.SetValue(y
);
2840 constr
->top
.SetDone(TRUE
);
2844 constr
->width
.SetValue(w
);
2845 constr
->width
.SetDone(TRUE
);
2849 constr
->height
.SetValue(h
);
2850 constr
->height
.SetDone(TRUE
);
2855 void wxWindow::MoveConstraint(int x
, int y
)
2857 wxLayoutConstraints
*constr
= GetConstraints();
2862 constr
->left
.SetValue(x
);
2863 constr
->left
.SetDone(TRUE
);
2867 constr
->top
.SetValue(y
);
2868 constr
->top
.SetDone(TRUE
);
2873 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2875 wxLayoutConstraints
*constr
= GetConstraints();
2878 *w
= constr
->width
.GetValue();
2879 *h
= constr
->height
.GetValue();
2885 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2887 wxLayoutConstraints
*constr
= GetConstraints();
2890 *w
= constr
->width
.GetValue();
2891 *h
= constr
->height
.GetValue();
2894 GetClientSize(w
, h
);
2897 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2899 wxLayoutConstraints
*constr
= GetConstraints();
2902 *x
= constr
->left
.GetValue();
2903 *y
= constr
->top
.GetValue();
2909 bool wxWindow::AcceptsFocus() const
2911 return IsEnabled() && IsShown();
2914 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )