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_scrollGC
= (GdkGC
*) NULL
;
916 m_widgetStyle
= (GtkStyle
*) 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_widgetStyle
) gtk_style_unref( m_widgetStyle
);
1037 if (m_scrollGC
) gdk_gc_unref( m_scrollGC
);
1039 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
1041 if (m_widget
) gtk_widget_destroy( m_widget
);
1045 DeleteRelatedConstraints();
1048 // This removes any dangling pointers to this window
1049 // in other windows' constraintsInvolvedIn lists.
1050 UnsetConstraints(m_constraints
);
1051 delete m_constraints
;
1052 m_constraints
= (wxLayoutConstraints
*) NULL
;
1056 delete m_windowSizer
;
1057 m_windowSizer
= (wxSizer
*) NULL
;
1059 // If this is a child of a sizer, remove self from parent
1060 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
1062 // Just in case the window has been Closed, but
1063 // we're then deleting immediately: don't leave
1064 // dangling pointers.
1065 wxPendingDelete
.DeleteObject(this);
1067 // Just in case we've loaded a top-level window via
1068 // wxWindow::LoadNativeDialog but we weren't a dialog
1070 wxTopLevelWindows
.DeleteObject(this);
1072 if (m_windowValidator
) delete m_windowValidator
;
1075 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1076 const wxPoint
&pos
, const wxSize
&size
,
1077 long style
, const wxString
&name
)
1079 if (m_needParent
&& (parent
== NULL
))
1080 wxFatalError( "Need complete parent.", name
);
1082 m_widget
= (GtkWidget
*) NULL
;
1085 m_children
.DeleteContents( FALSE
);
1089 if (m_width
== -1) m_width
= 20;
1091 if (m_height
== -1) m_height
= 20;
1097 m_eventHandler
= this;
1100 if (m_cursor
== NULL
)
1101 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1102 m_font
= *wxSWISS_FONT
;
1103 // m_backgroundColour = wxWHITE;
1104 m_foregroundColour
= wxBLACK
;
1105 m_windowStyle
= style
;
1106 m_windowName
= name
;
1107 m_constraints
= (wxLayoutConstraints
*) NULL
;
1108 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1109 m_windowSizer
= (wxSizer
*) NULL
;
1110 m_sizerParent
= (wxWindow
*) NULL
;
1111 m_autoLayout
= FALSE
;
1112 m_hasScrolling
= FALSE
;
1113 m_isScrolling
= FALSE
;
1114 m_pDropTarget
= (wxDropTarget
*) NULL
;
1116 m_windowValidator
= (wxValidator
*) NULL
;
1117 m_scrollGC
= (GdkGC
*) NULL
;
1118 m_widgetStyle
= (GtkStyle
*) NULL
;
1121 void wxWindow::PostCreation()
1123 if (m_parent
) m_parent
->AddChild( this );
1127 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1128 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1130 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1131 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1134 ConnectWidget( GetConnectWidget() );
1136 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1138 if (m_wxwindow
) gtk_widget_realize( m_wxwindow
);
1140 SetCursor( *wxSTANDARD_CURSOR
);
1145 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1147 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1148 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1150 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1151 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1153 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1154 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1156 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1157 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1159 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1160 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1162 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1163 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1165 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1166 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1168 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1169 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1172 bool wxWindow::HasVMT()
1177 bool wxWindow::Close( bool force
)
1179 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1181 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1182 event
.SetEventObject(this);
1183 event
.SetForce(force
);
1185 return GetEventHandler()->ProcessEvent(event
);
1188 bool wxWindow::Destroy()
1190 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1197 bool wxWindow::DestroyChildren()
1202 while ((node
= GetChildren()->First()) != (wxNode
*)NULL
)
1205 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1208 if (GetChildren()->Member(child
)) delete node
;
1215 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1217 // are we to set fonts here ?
1220 void wxWindow::ImplementSetSize()
1222 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1223 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1224 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_minWidth
;
1225 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_minHeight
;
1226 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1229 void wxWindow::ImplementSetPosition()
1231 if (IS_KIND_OF(this,wxFrame
) || IS_KIND_OF(this,wxDialog
))
1233 if ((m_x
!= -1) || (m_y
!= -1))
1234 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
1240 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1244 if ((m_parent
) && (m_parent
->m_wxwindow
))
1245 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
, m_y
);
1247 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1250 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1252 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1254 if (m_resizing
) return; // I don't like recursions
1262 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1264 if (newX
== -1) newX
= m_x
;
1265 if (newY
== -1) newY
= m_y
;
1266 if (newW
== -1) newW
= m_width
;
1267 if (newH
== -1) newH
= m_height
;
1270 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1272 if (newW
== -1) newW
= 80;
1275 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1277 if (newH
== -1) newH
= 26;
1280 if ((m_x
!= newX
) || (m_y
!= newY
) || (!m_sizeSet
))
1284 ImplementSetPosition();
1286 if ((m_width
!= newW
) || (m_height
!= newH
) || (!m_sizeSet
))
1294 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1295 event
.SetEventObject( this );
1296 ProcessEvent( event
);
1301 void wxWindow::SetSize( int width
, int height
)
1303 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1306 void wxWindow::Move( int x
, int y
)
1308 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1311 void wxWindow::GetSize( int *width
, int *height
) const
1313 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1315 if (width
) (*width
) = m_width
;
1316 if (height
) (*height
) = m_height
;
1319 void wxWindow::SetClientSize( int width
, int height
)
1321 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1325 SetSize( width
, height
);
1332 if (!m_hasScrolling
)
1335 do we have sunken dialogs ?
1337 GtkStyleClass *window_class = m_wxwindow->style->klass;
1339 dw += 2 * window_class->xthickness;
1340 dh += 2 * window_class->ythickness;
1345 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1346 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1348 GtkWidget
*viewport
= scroll_window
->viewport
;
1349 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1351 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1352 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1354 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1355 (m_windowStyle
& wxSUNKEN_BORDER
))
1357 dw
+= 2 * viewport_class
->xthickness
;
1358 dh
+= 2 * viewport_class
->ythickness
;
1361 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1363 dw
+= vscrollbar
->allocation
.width
;
1364 dw
+= scroll_class
->scrollbar_spacing
;
1367 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1369 dh
+= hscrollbar
->allocation
.height
;
1370 dw
+= scroll_class
->scrollbar_spacing
;
1374 SetSize( width
+dw
, height
+dh
);
1378 void wxWindow::GetClientSize( int *width
, int *height
) const
1380 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1384 if (width
) (*width
) = m_width
;
1385 if (height
) (*height
) = m_height
;
1392 if (!m_hasScrolling
)
1395 do we have sunken dialogs ?
1397 GtkStyleClass *window_class = m_wxwindow->style->klass;
1399 dw += 2 * window_class->xthickness;
1400 dh += 2 * window_class->ythickness;
1405 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1406 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1408 GtkWidget
*viewport
= scroll_window
->viewport
;
1409 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1411 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1412 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1414 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1415 (m_windowStyle
& wxSUNKEN_BORDER
))
1417 dw
+= 2 * viewport_class
->xthickness
;
1418 dh
+= 2 * viewport_class
->ythickness
;
1421 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1423 // dw += vscrollbar->allocation.width;
1424 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1425 dw
+= scroll_class
->scrollbar_spacing
;
1428 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1430 // dh += hscrollbar->allocation.height;
1432 dh
+= scroll_class
->scrollbar_spacing
;
1436 if (width
) (*width
) = m_width
- dw
;
1437 if (height
) (*height
) = m_height
- dh
;
1441 void wxWindow::GetPosition( int *x
, int *y
) const
1443 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1449 void wxWindow::ClientToScreen( int *x
, int *y
)
1451 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1453 GdkWindow
*source
= (GdkWindow
*) NULL
;
1455 source
= m_wxwindow
->window
;
1457 source
= m_widget
->window
;
1461 gdk_window_get_origin( source
, &org_x
, &org_y
);
1465 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1467 org_x
+= m_widget
->allocation
.x
;
1468 org_y
+= m_widget
->allocation
.y
;
1476 void wxWindow::ScreenToClient( int *x
, int *y
)
1478 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1480 GdkWindow
*source
= (GdkWindow
*) NULL
;
1482 source
= m_wxwindow
->window
;
1484 source
= m_widget
->window
;
1488 gdk_window_get_origin( source
, &org_x
, &org_y
);
1492 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1494 org_x
+= m_widget
->allocation
.x
;
1495 org_y
+= m_widget
->allocation
.y
;
1503 void wxWindow::Centre( int direction
)
1505 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1507 if (IS_KIND_OF(this,wxDialog
) || IS_KIND_OF(this,wxFrame
))
1509 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (gdk_screen_width () - m_width
) / 2;
1510 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (gdk_screen_height () - m_height
) / 2;
1511 ImplementSetPosition();
1519 m_parent
->GetSize( &p_w
, &p_h
);
1520 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (p_w
- m_width
) / 2;
1521 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (p_h
- m_height
) / 2;
1522 ImplementSetPosition();
1527 void wxWindow::Fit()
1529 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1533 wxNode
*node
= GetChildren()->First();
1536 wxWindow
*win
= (wxWindow
*)node
->Data();
1538 win
->GetPosition(&wx
, &wy
);
1539 win
->GetSize(&ww
, &wh
);
1540 if ( wx
+ ww
> maxX
)
1542 if ( wy
+ wh
> maxY
)
1545 node
= node
->Next();
1547 SetClientSize(maxX
+ 5, maxY
+ 10);
1550 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1552 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1560 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1562 //if (GetAutoLayout()) Layout();
1565 bool wxWindow::Show( bool show
)
1567 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1570 gtk_widget_show( m_widget
);
1572 gtk_widget_hide( m_widget
);
1577 void wxWindow::Enable( bool enable
)
1579 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1581 m_isEnabled
= enable
;
1582 gtk_widget_set_sensitive( m_widget
, enable
);
1583 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1586 int wxWindow::GetCharHeight() const
1588 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1592 wxFAIL_MSG( "invalid font" );
1596 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1597 return font
->ascent
+ font
->descent
;
1600 int wxWindow::GetCharWidth() const
1602 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1606 wxFAIL_MSG( "invalid font" );
1610 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1611 return gdk_string_width( font
, "H" );
1614 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1615 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1617 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1619 wxFont fontToUse
= m_font
;
1620 if (theFont
) fontToUse
= *theFont
;
1622 if (!fontToUse
.Ok())
1624 wxFAIL_MSG( "invalid font" );
1627 wxASSERT_MSG( (m_font
.Ok()), "invalid font" );
1629 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1630 if (x
) (*x
) = gdk_string_width( font
, string
);
1631 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1632 if (descent
) (*descent
) = font
->descent
;
1633 if (externalLeading
) (*externalLeading
) = 0; // ??
1636 void wxWindow::MakeModal( bool modal
)
1639 // Disable all other windows
1640 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1642 wxNode
*node
= wxTopLevelWindows
.First();
1645 wxWindow
*win
= (wxWindow
*)node
->Data();
1647 win
->Enable(!modal
);
1649 node
= node
->Next();
1654 void wxWindow::SetFocus()
1656 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1658 GtkWidget
*connect_widget
= GetConnectWidget();
1661 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) && !GTK_WIDGET_HAS_FOCUS (connect_widget
) )
1663 gtk_widget_grab_focus (connect_widget
);
1668 bool wxWindow::OnClose()
1673 void wxWindow::AddChild( wxWindow
*child
)
1675 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1676 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window need client area" );
1677 wxASSERT_MSG( (child
!= NULL
), "invalid child" );
1678 wxASSERT_MSG( (child
->m_widget
!= NULL
), "invalid child" );
1680 // Addchild is (often) called before the program
1681 // has left the parents constructor so that no
1682 // virtual tables work yet. The approach below
1683 // practically imitates virtual tables, i.e. it
1684 // implements a different AddChild() behaviour
1685 // for wxFrame, wxDialog, wxWindow and
1686 // wxMDIParentFrame.
1688 // wxFrame and wxDialog as children aren't placed into the parents
1690 if (( IS_KIND_OF(child
,wxFrame
) || IS_KIND_OF(child
,wxDialog
) ) &&
1691 (!IS_KIND_OF(child
,wxMDIChildFrame
)))
1693 m_children
.Append( child
);
1695 if ((child
->m_x
!= -1) && (child
->m_y
!= -1))
1696 gtk_widget_set_uposition( child
->m_widget
, child
->m_x
, child
->m_y
);
1701 // In the case of an wxMDIChildFrame descendant, we use the
1702 // client windows's AddChild()
1704 if (IS_KIND_OF(this,wxMDIParentFrame
))
1706 if (IS_KIND_OF(child
,wxMDIChildFrame
))
1708 wxMDIClientWindow
*client
= ((wxMDIParentFrame
*)this)->GetClientWindow();
1711 client
->AddChild( child
);
1717 // wxNotebook is very special, so it has a private AddChild()
1719 if (IS_KIND_OF(this,wxNotebook
))
1721 wxNotebook
*tab
= (wxNotebook
*)this;
1722 tab
->AddChild( child
);
1726 // wxFrame has a private AddChild
1728 if (IS_KIND_OF(this,wxFrame
) && !IS_KIND_OF(this,wxMDIChildFrame
))
1730 wxFrame
*frame
= (wxFrame
*)this;
1731 frame
->AddChild( child
);
1737 m_children
.Append( child
);
1738 if (m_wxwindow
) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), child
->m_widget
,
1739 child
->m_x
, child
->m_y
);
1741 gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height
);
1744 wxList
*wxWindow::GetChildren()
1746 return (&m_children
);
1749 void wxWindow::RemoveChild( wxWindow
*child
)
1752 GetChildren()->DeleteObject( child
);
1753 child
->m_parent
= (wxWindow
*) NULL
;
1756 void wxWindow::SetReturnCode( int retCode
)
1758 m_retCode
= retCode
;
1761 int wxWindow::GetReturnCode()
1766 void wxWindow::Raise()
1768 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1770 if (m_widget
) gdk_window_raise( m_widget
->window
);
1773 void wxWindow::Lower()
1775 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1777 if (m_widget
) gdk_window_lower( m_widget
->window
);
1780 wxEvtHandler
*wxWindow::GetEventHandler()
1782 return m_eventHandler
;
1785 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
1787 m_eventHandler
= handler
;
1790 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
1792 handler
->SetNextHandler(GetEventHandler());
1793 SetEventHandler(handler
);
1796 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
1798 if (GetEventHandler())
1800 wxEvtHandler
*handlerA
= GetEventHandler();
1801 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
1802 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
1803 SetEventHandler(handlerB
);
1807 return (wxEvtHandler
*) NULL
;
1813 return (wxEvtHandler
*) NULL
;
1816 wxValidator
*wxWindow::GetValidator()
1818 return m_windowValidator
;
1821 void wxWindow::SetValidator( const wxValidator
& validator
)
1823 if (m_windowValidator
) delete m_windowValidator
;
1824 m_windowValidator
= validator
.Clone();
1825 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
1828 bool wxWindow::IsBeingDeleted()
1833 void wxWindow::SetId( wxWindowID id
)
1838 wxWindowID
wxWindow::GetId()
1843 void wxWindow::SetCursor( const wxCursor
&cursor
)
1845 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1847 if (m_cursor
== NULL
)
1849 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1850 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1855 if (*((wxCursor
*)&cursor
) == m_cursor
) return;
1860 *m_cursor
= *wxSTANDARD_CURSOR
;
1863 if ((m_widget
) && (m_widget
->window
))
1864 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
1866 if ((m_wxwindow
) && (m_wxwindow
->window
))
1867 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
1870 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
1872 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1874 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
1877 gdk_window_clear_area( m_wxwindow
->window
,
1891 GetClientSize( &w
, &h
);
1893 GdkRectangle gdk_rect
;
1897 gdk_rect
.height
= h
;
1898 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1903 GdkRectangle gdk_rect
;
1904 gdk_rect
.x
= rect
->x
;
1905 gdk_rect
.y
= rect
->y
;
1906 gdk_rect
.width
= rect
->width
;
1907 gdk_rect
.height
= rect
->height
;
1910 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1912 gtk_widget_draw( m_widget
, &gdk_rect
);
1916 wxRegion
wxWindow::GetUpdateRegion() const
1918 return m_updateRegion
;
1921 bool wxWindow::IsExposed( int x
, int y
) const
1923 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
1926 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
1928 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
1931 bool wxWindow::IsExposed( const wxPoint
& pt
) const
1933 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
1936 bool wxWindow::IsExposed( const wxRect
& rect
) const
1938 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
1941 void wxWindow::Clear()
1943 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
1945 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
1948 wxColour
wxWindow::GetBackgroundColour() const
1950 return m_backgroundColour
;
1953 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
1955 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
1957 m_backgroundColour
= colour
;
1958 if (!m_backgroundColour
.Ok()) return;
1962 GdkWindow
*window
= m_wxwindow
->window
;
1963 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
1964 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
1965 gdk_window_clear( window
);
1969 GtkStyle
*style
= GetWidgetStyle();
1970 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
1971 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
1972 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
1973 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
1974 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
1975 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
1976 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
1977 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
1978 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
1982 wxColour
wxWindow::GetForegroundColour() const
1984 return m_foregroundColour
;
1987 void wxWindow::SetForegroundColour( const wxColour
&colour
)
1989 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
1991 m_foregroundColour
= colour
;
1992 if (!m_foregroundColour
.Ok()) return;
1996 GtkStyle
*style
= GetWidgetStyle();
1997 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
1998 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
1999 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2000 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2004 GtkStyle
*wxWindow::GetWidgetStyle()
2009 gtk_widget_get_style( m_widget
) );
2010 return m_widgetStyle
;
2013 bool wxWindow::Validate()
2015 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2017 wxNode
*node
= GetChildren()->First();
2020 wxWindow
*child
= (wxWindow
*)node
->Data();
2021 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
2023 node
= node
->Next();
2028 bool wxWindow::TransferDataToWindow()
2030 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2032 wxNode
*node
= GetChildren()->First();
2035 wxWindow
*child
= (wxWindow
*)node
->Data();
2036 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
2037 !child
->GetValidator()->TransferToWindow() )
2039 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
2042 node
= node
->Next();
2047 bool wxWindow::TransferDataFromWindow()
2049 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2051 wxNode
*node
= GetChildren()->First();
2054 wxWindow
*child
= (wxWindow
*)node
->Data();
2055 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
2057 node
= node
->Next();
2062 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
2064 m_acceleratorTable
= accel
;
2067 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
2069 TransferDataToWindow();
2072 void wxWindow::InitDialog()
2074 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2076 wxInitDialogEvent
event(GetId());
2077 event
.SetEventObject( this );
2078 GetEventHandler()->ProcessEvent(event
);
2081 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2083 menu
->SetInvokingWindow( win
);
2084 wxNode
*node
= menu
->m_items
.First();
2087 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2088 if (menuitem
->IsSubMenu())
2089 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2090 node
= node
->Next();
2094 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
2096 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2098 SetInvokingWindow( menu
, this );
2100 GTK_MENU(menu
->m_menu
),
2101 (GtkWidget
*)NULL
, // parent menu shell
2102 (GtkWidget
*)NULL
, // parent menu item
2103 (GtkMenuPositionFunc
)NULL
,
2104 NULL
, // client data
2105 0, // button used to activate it
2106 0//gs_timeLastClick // the time of activation
2111 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2113 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2115 GtkWidget
*dnd_widget
= GetConnectWidget();
2117 DisconnectDnDWidget( dnd_widget
);
2119 if (m_pDropTarget
) delete m_pDropTarget
;
2120 m_pDropTarget
= dropTarget
;
2122 ConnectDnDWidget( dnd_widget
);
2125 wxDropTarget
*wxWindow::GetDropTarget() const
2127 return m_pDropTarget
;
2130 void wxWindow::ConnectDnDWidget( GtkWidget
*widget
)
2132 if (!m_pDropTarget
) return;
2134 m_pDropTarget
->RegisterWidget( widget
);
2136 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
2137 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2140 void wxWindow::DisconnectDnDWidget( GtkWidget
*widget
)
2142 if (!m_pDropTarget
) return;
2144 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
2145 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2147 m_pDropTarget
->UnregisterWidget( widget
);
2150 GtkWidget
* wxWindow::GetConnectWidget()
2152 GtkWidget
*connect_widget
= m_widget
;
2153 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2155 return connect_widget
;
2158 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2160 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2161 return (window
== m_widget
->window
);
2164 void wxWindow::SetFont( const wxFont
&font
)
2166 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2168 if (((wxFont
*)&font
)->Ok())
2171 m_font
= *wxSWISS_FONT
;
2173 GtkStyle
*style
= GetWidgetStyle();
2174 gdk_font_unref( style
->font
);
2175 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2178 wxFont
*wxWindow::GetFont()
2183 void wxWindow::SetWindowStyleFlag( long flag
)
2185 m_windowStyle
= flag
;
2188 long wxWindow::GetWindowStyleFlag() const
2190 return m_windowStyle
;
2193 void wxWindow::CaptureMouse()
2195 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2197 wxASSERT_MSG( (g_capturing
== FALSE
), "CaptureMouse called twice" );
2199 GtkWidget
*connect_widget
= GetConnectWidget();
2200 gtk_grab_add( connect_widget
);
2201 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
2203 (GDK_BUTTON_PRESS_MASK
|
2204 GDK_BUTTON_RELEASE_MASK
|
2205 GDK_POINTER_MOTION_MASK
),
2206 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
2210 void wxWindow::ReleaseMouse()
2212 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2214 wxASSERT_MSG( (g_capturing
== TRUE
), "ReleaseMouse called twice" );
2216 GtkWidget
*connect_widget
= GetConnectWidget();
2217 gtk_grab_remove( connect_widget
);
2218 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2219 g_capturing
= FALSE
;
2222 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2226 wxString
wxWindow::GetTitle() const
2228 return (wxString
&)m_windowName
;
2231 wxString
wxWindow::GetLabel() const
2236 void wxWindow::SetName( const wxString
&name
)
2238 m_windowName
= name
;
2241 wxString
wxWindow::GetName() const
2243 return (wxString
&)m_windowName
;
2246 bool wxWindow::IsShown() const
2251 bool wxWindow::IsRetained()
2256 wxWindow
*wxWindow::FindWindow( long id
)
2258 if (id
== m_windowId
) return this;
2259 wxNode
*node
= m_children
.First();
2262 wxWindow
*child
= (wxWindow
*)node
->Data();
2263 wxWindow
*res
= child
->FindWindow( id
);
2264 if (res
) return res
;
2265 node
= node
->Next();
2267 return (wxWindow
*) NULL
;
2270 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2272 if (name
== m_windowName
) return this;
2273 wxNode
*node
= m_children
.First();
2276 wxWindow
*child
= (wxWindow
*)node
->Data();
2277 wxWindow
*res
= child
->FindWindow( name
);
2278 if (res
) return res
;
2279 node
= node
->Next();
2281 return (wxWindow
*) NULL
;
2284 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2285 int range
, bool refresh
)
2287 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2289 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2291 if (!m_wxwindow
) return;
2293 if (orient
== wxHORIZONTAL
)
2295 float fpos
= (float)pos
;
2296 float frange
= (float)range
;
2297 float fthumb
= (float)thumbVisible
;
2299 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2300 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2302 SetScrollPos( orient
, pos
, refresh
);
2306 m_oldHorizontalPos
= fpos
;
2308 m_hAdjust
->lower
= 0.0;
2309 m_hAdjust
->upper
= frange
;
2310 m_hAdjust
->value
= fpos
;
2311 m_hAdjust
->step_increment
= 1.0;
2312 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2313 m_hAdjust
->page_size
= fthumb
;
2317 float fpos
= (float)pos
;
2318 float frange
= (float)range
;
2319 float fthumb
= (float)thumbVisible
;
2321 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2322 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2324 SetScrollPos( orient
, pos
, refresh
);
2328 m_oldVerticalPos
= fpos
;
2330 m_vAdjust
->lower
= 0.0;
2331 m_vAdjust
->upper
= frange
;
2332 m_vAdjust
->value
= fpos
;
2333 m_vAdjust
->step_increment
= 1.0;
2334 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2335 m_vAdjust
->page_size
= fthumb
;
2338 if (m_wxwindow
->window
)
2340 if (orient
== wxHORIZONTAL
)
2341 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2343 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2345 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2349 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2351 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2353 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2355 if (!m_wxwindow
) return;
2357 if (orient
== wxHORIZONTAL
)
2359 float fpos
= (float)pos
;
2360 m_oldHorizontalPos
= fpos
;
2362 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2363 m_hAdjust
->value
= fpos
;
2367 float fpos
= (float)pos
;
2368 m_oldVerticalPos
= fpos
;
2369 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2370 m_vAdjust
->value
= fpos
;
2375 if (m_wxwindow
->window
)
2377 if (orient
== wxHORIZONTAL
)
2378 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2380 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2385 int wxWindow::GetScrollThumb( int orient
) const
2387 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2389 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2391 if (!m_wxwindow
) return 0;
2393 if (orient
== wxHORIZONTAL
)
2394 return (int)(m_hAdjust
->page_size
+0.5);
2396 return (int)(m_vAdjust
->page_size
+0.5);
2399 int wxWindow::GetScrollPos( int orient
) const
2401 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2403 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2405 if (!m_wxwindow
) return 0;
2407 if (orient
== wxHORIZONTAL
)
2408 return (int)(m_hAdjust
->value
+0.5);
2410 return (int)(m_vAdjust
->value
+0.5);
2413 int wxWindow::GetScrollRange( int orient
) const
2415 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2417 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2419 if (!m_wxwindow
) return 0;
2421 if (orient
== wxHORIZONTAL
)
2422 return (int)(m_hAdjust
->upper
+0.5);
2424 return (int)(m_vAdjust
->upper
+0.5);
2427 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2429 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2431 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2433 if (!m_wxwindow
) return;
2437 GetClientSize( &cw
, &ch
);
2439 int w
= cw
- abs(dx
);
2440 int h
= ch
- abs(dy
);
2441 if ((h
< 0) || (w
< 0))
2448 if (dx
< 0) s_x
= -dx
;
2449 if (dy
< 0) s_y
= -dy
;
2452 if (dx
> 0) d_x
= dx
;
2453 if (dy
> 0) d_y
= dy
;
2457 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2458 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2461 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2462 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2465 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2466 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2467 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2468 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2470 Refresh( TRUE
, &rect
);
2473 //-------------------------------------------------------------------------------------
2475 //-------------------------------------------------------------------------------------
2477 wxLayoutConstraints
*wxWindow::GetConstraints() const
2479 return m_constraints
;
2482 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2486 UnsetConstraints(m_constraints
);
2487 delete m_constraints
;
2489 m_constraints
= constraints
;
2492 // Make sure other windows know they're part of a 'meaningful relationship'
2493 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2494 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2495 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2496 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2497 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2498 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2499 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2500 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2501 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2502 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2503 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2504 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2505 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2506 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2507 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2508 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2514 void wxWindow::SetAutoLayout( bool autoLayout
)
2516 m_autoLayout
= autoLayout
;
2519 bool wxWindow::GetAutoLayout() const
2521 return m_autoLayout
;
2524 wxSizer
*wxWindow::GetSizer() const
2526 return m_windowSizer
;
2529 void wxWindow::SetSizerParent( wxWindow
*win
)
2531 m_sizerParent
= win
;
2534 wxWindow
*wxWindow::GetSizerParent() const
2536 return m_sizerParent
;
2539 // This removes any dangling pointers to this window
2540 // in other windows' constraintsInvolvedIn lists.
2541 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2545 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2546 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2547 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2548 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2549 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2550 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2551 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2552 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2553 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2554 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2555 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2556 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2557 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2558 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2559 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2560 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2564 // Back-pointer to other windows we're involved with, so if we delete
2565 // this window, we must delete any constraints we're involved with.
2566 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2568 if (!m_constraintsInvolvedIn
)
2569 m_constraintsInvolvedIn
= new wxList
;
2570 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2571 m_constraintsInvolvedIn
->Append(otherWin
);
2574 // REMOVE back-pointer to other windows we're involved with.
2575 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2577 if (m_constraintsInvolvedIn
)
2578 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2581 // Reset any constraints that mention this window
2582 void wxWindow::DeleteRelatedConstraints()
2584 if (m_constraintsInvolvedIn
)
2586 wxNode
*node
= m_constraintsInvolvedIn
->First();
2589 wxWindow
*win
= (wxWindow
*)node
->Data();
2590 wxNode
*next
= node
->Next();
2591 wxLayoutConstraints
*constr
= win
->GetConstraints();
2593 // Reset any constraints involving this window
2596 constr
->left
.ResetIfWin((wxWindow
*)this);
2597 constr
->top
.ResetIfWin((wxWindow
*)this);
2598 constr
->right
.ResetIfWin((wxWindow
*)this);
2599 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2600 constr
->width
.ResetIfWin((wxWindow
*)this);
2601 constr
->height
.ResetIfWin((wxWindow
*)this);
2602 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2603 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2608 delete m_constraintsInvolvedIn
;
2609 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2613 void wxWindow::SetSizer(wxSizer
*sizer
)
2615 m_windowSizer
= sizer
;
2617 sizer
->SetSizerParent((wxWindow
*)this);
2624 bool wxWindow::Layout()
2626 if (GetConstraints())
2629 GetClientSize(&w
, &h
);
2630 GetConstraints()->width
.SetValue(w
);
2631 GetConstraints()->height
.SetValue(h
);
2634 // If top level (one sizer), evaluate the sizer's constraints.
2638 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2639 GetSizer()->LayoutPhase1(&noChanges
);
2640 GetSizer()->LayoutPhase2(&noChanges
);
2641 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2646 // Otherwise, evaluate child constraints
2647 ResetConstraints(); // Mark all constraints as unevaluated
2648 DoPhase(1); // Just one phase need if no sizers involved
2650 SetConstraintSizes(); // Recursively set the real window sizes
2656 // Do a phase of evaluating constraints:
2657 // the default behaviour. wxSizers may do a similar
2658 // thing, but also impose their own 'constraints'
2659 // and order the evaluation differently.
2660 bool wxWindow::LayoutPhase1(int *noChanges
)
2662 wxLayoutConstraints
*constr
= GetConstraints();
2665 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2671 bool wxWindow::LayoutPhase2(int *noChanges
)
2681 // Do a phase of evaluating child constraints
2682 bool wxWindow::DoPhase(int phase
)
2684 int noIterations
= 0;
2685 int maxIterations
= 500;
2689 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2693 wxNode
*node
= GetChildren()->First();
2696 wxWindow
*child
= (wxWindow
*)node
->Data();
2697 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2699 wxLayoutConstraints
*constr
= child
->GetConstraints();
2702 if (succeeded
.Member(child
))
2707 int tempNoChanges
= 0;
2708 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2709 noChanges
+= tempNoChanges
;
2712 succeeded
.Append(child
);
2717 node
= node
->Next();
2724 void wxWindow::ResetConstraints()
2726 wxLayoutConstraints
*constr
= GetConstraints();
2729 constr
->left
.SetDone(FALSE
);
2730 constr
->top
.SetDone(FALSE
);
2731 constr
->right
.SetDone(FALSE
);
2732 constr
->bottom
.SetDone(FALSE
);
2733 constr
->width
.SetDone(FALSE
);
2734 constr
->height
.SetDone(FALSE
);
2735 constr
->centreX
.SetDone(FALSE
);
2736 constr
->centreY
.SetDone(FALSE
);
2738 wxNode
*node
= GetChildren()->First();
2741 wxWindow
*win
= (wxWindow
*)node
->Data();
2742 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2743 win
->ResetConstraints();
2744 node
= node
->Next();
2748 // Need to distinguish between setting the 'fake' size for
2749 // windows and sizers, and setting the real values.
2750 void wxWindow::SetConstraintSizes(bool recurse
)
2752 wxLayoutConstraints
*constr
= GetConstraints();
2753 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2754 constr
->width
.GetDone() && constr
->height
.GetDone())
2756 int x
= constr
->left
.GetValue();
2757 int y
= constr
->top
.GetValue();
2758 int w
= constr
->width
.GetValue();
2759 int h
= constr
->height
.GetValue();
2761 // If we don't want to resize this window, just move it...
2762 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2763 (constr
->height
.GetRelationship() != wxAsIs
))
2765 // Calls Layout() recursively. AAAGH. How can we stop that.
2766 // Simply take Layout() out of non-top level OnSizes.
2767 SizerSetSize(x
, y
, w
, h
);
2776 char *windowClass
= this->GetClassInfo()->GetClassName();
2779 if (GetName() == "")
2780 winName
= _("unnamed");
2782 winName
= GetName();
2783 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2784 if (!constr
->left
.GetDone())
2785 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2786 if (!constr
->right
.GetDone())
2787 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2788 if (!constr
->width
.GetDone())
2789 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2790 if (!constr
->height
.GetDone())
2791 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2792 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2797 wxNode
*node
= GetChildren()->First();
2800 wxWindow
*win
= (wxWindow
*)node
->Data();
2801 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2802 win
->SetConstraintSizes();
2803 node
= node
->Next();
2808 // This assumes that all sizers are 'on' the same
2809 // window, i.e. the parent of this window.
2810 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2812 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2813 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2817 m_sizerParent
->GetPosition(&xp
, &yp
);
2818 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2823 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2827 TransformSizerToActual(&xx
, &yy
);
2828 SetSize(xx
, yy
, w
, h
);
2831 void wxWindow::SizerMove(int x
, int y
)
2835 TransformSizerToActual(&xx
, &yy
);
2839 // Only set the size/position of the constraint (if any)
2840 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2842 wxLayoutConstraints
*constr
= GetConstraints();
2847 constr
->left
.SetValue(x
);
2848 constr
->left
.SetDone(TRUE
);
2852 constr
->top
.SetValue(y
);
2853 constr
->top
.SetDone(TRUE
);
2857 constr
->width
.SetValue(w
);
2858 constr
->width
.SetDone(TRUE
);
2862 constr
->height
.SetValue(h
);
2863 constr
->height
.SetDone(TRUE
);
2868 void wxWindow::MoveConstraint(int x
, int y
)
2870 wxLayoutConstraints
*constr
= GetConstraints();
2875 constr
->left
.SetValue(x
);
2876 constr
->left
.SetDone(TRUE
);
2880 constr
->top
.SetValue(y
);
2881 constr
->top
.SetDone(TRUE
);
2886 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2888 wxLayoutConstraints
*constr
= GetConstraints();
2891 *w
= constr
->width
.GetValue();
2892 *h
= constr
->height
.GetValue();
2898 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2900 wxLayoutConstraints
*constr
= GetConstraints();
2903 *w
= constr
->width
.GetValue();
2904 *h
= constr
->height
.GetValue();
2907 GetClientSize(w
, h
);
2910 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2912 wxLayoutConstraints
*constr
= GetConstraints();
2915 *x
= constr
->left
.GetValue();
2916 *y
= constr
->top
.GetValue();
2922 bool wxWindow::AcceptsFocus() const
2924 return IsEnabled() && IsShown();
2927 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )