1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
7 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "window.h"
17 #include "wx/window.h"
21 #include "wx/layout.h"
23 #include "wx/dialog.h"
24 #include "wx/msgdlg.h"
25 #include "wx/dcclient.h"
29 #include "wx/notebook.h"
30 #include "wx/statusbr.h"
32 #include "wx/gtk/win_gtk.h"
33 #include "gdk/gdkprivate.h"
34 #include "gdk/gdkkeysyms.h"
38 //-----------------------------------------------------------------------------
39 // documentation on internals
40 //-----------------------------------------------------------------------------
43 I have been asked several times about writing some documentation about
44 the GTK port of wxWindows, especially its internal structures. Obviously,
45 you cannot understand wxGTK without knowing a little about the GTK, but
46 some more information about what the wxWindow, which is the base class
47 for all other window classes, does seems required as well.
49 What does wxWindow do? It contains the common interface for the following
50 jobs of its descentants:
52 1) Define the rudimentary behaviour common to all window classes, such as
53 resizing, intercepting user input so as to make it possible to use these
54 events for special purposes in a derived class, window names etc.
56 2) Provide the possibility to contain and manage children, if the derived
57 class is allowed to contain children, which holds true for those window
58 classes, which do not display a native GTK widget. To name them, these
59 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
60 work classes are a special case and are handled a bit differently from
63 3) Provide the possibility to draw into a client area of a window. This,
64 too, only holds true for classes that do not display a native GTK widget
67 4) Provide the entire mechanism for scrolling widgets. This actaul inter-
68 face for this is usually in wxScrolledWidget, but the GTK implementation
71 5) A multitude of helper or extra methods for special purposes, such as
72 Drag'n'Drop, managing validators etc.
74 Normally one might expect, that one wxWindows class would always contain
75 one GTK widget. Under GTK, there is no such allround widget that has all
76 the functionality. Moreover, the GTK defines a client area as a different
77 widget from the actual widget you are handling. Last but not least some
78 special classes (e.g. wxFrame) handle different categories of widgets and
79 still have the possibility to draw something in the client area.
80 It was therefore required to write a special purpose GTK widget, that would
81 represent a client area in the sense of wxWindows capable to do the jobs
82 2), 3) and 4). I have written this class and it resides in win_gtk.c of
85 All windows must have a widget, with which they interact with other under-
86 lying GTK widget. It is this widget, e.g. that has to be resized etc and
87 thw wxWindow class has a member variable called m_widget which holds a
88 pointer to this widget. When the window class displays a GTK native widget,
89 this is the only GTK widget the class manages. When the class has a client
90 area for drawing into and for containing children it must have at least
91 one more GTK widget to handle (of the type GtkMyFixed, defined in win_gtk.c),
92 but there can be any number of widgets, handled by a class (e.g. the frame
93 class handles three). The common rule for all windows is only, that the
94 widget that interacts with the rest of GTK must be referenced in m_widget
95 and all other widgets must be children of this widget on the GTK level.
96 The top-most widget, which also represents the client area, must be in
97 the m_wxwindow field and must be of the type GtkMyFixed.
99 As I said, the window classes that display a GTK native widget only have
100 one widget, so in the case of e.g. the wxButton class m_widget holds a
101 pointer to a GtkButton widget. But windows with client areas (for drawing
102 and children) have a m_widget field that is a pointer to a GtkScrolled-
103 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
104 one is (in the GTK sense) a child of the GtkScrolledWindow.
106 If the m_wxwindow field is set, then all input to this widget is inter-
107 cepted and sent to the wxWindows class. If not, all input to the widget
108 that gets pointed to by m_widget gets intercepted and sent to the class.
112 //-----------------------------------------------------------------------------
114 //-----------------------------------------------------------------------------
116 extern wxList wxPendingDelete
;
117 extern wxList wxTopLevelWindows
;
118 extern bool g_blockEventsOnDrag
;
119 bool g_capturing
= FALSE
;
121 //-----------------------------------------------------------------------------
122 // "expose_event" (of m_wxwindow, not of m_widget)
123 //-----------------------------------------------------------------------------
125 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
127 if (!win
->HasVMT()) return;
128 if (g_blockEventsOnDrag
) return;
130 win
->m_updateRegion
.Union( gdk_event
->area
.x
,
132 gdk_event
->area
.width
,
133 gdk_event
->area
.height
);
135 if (gdk_event
->count
> 0) return;
138 printf( "OnExpose from " );
139 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
140 printf( win->GetClassInfo()->GetClassName() );
144 wxPaintEvent
event( win
->GetId() );
145 event
.SetEventObject( win
);
146 win
->GetEventHandler()->ProcessEvent( event
);
148 win
->m_updateRegion
.Clear();
151 //-----------------------------------------------------------------------------
152 // "draw" (of m_wxwindow, not of m_widget)
153 //-----------------------------------------------------------------------------
155 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
157 if (!win
->HasVMT()) return;
158 if (g_blockEventsOnDrag
) return;
160 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
162 wxPaintEvent
event( win
->GetId() );
163 event
.SetEventObject( win
);
164 win
->GetEventHandler()->ProcessEvent( event
);
166 win
->m_updateRegion
.Clear();
169 //-----------------------------------------------------------------------------
171 //-----------------------------------------------------------------------------
173 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
175 if (!win
->HasVMT()) return FALSE
;
176 if (g_blockEventsOnDrag
) return FALSE
;
179 printf( "OnKeyPress from " );
180 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
181 printf( win->GetClassInfo()->GetClassName() );
186 switch (gdk_event
->keyval
)
188 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
189 case GDK_Tab
: key_code
= WXK_TAB
; break;
190 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
191 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
192 case GDK_Return
: key_code
= WXK_RETURN
; break;
193 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
194 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
195 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
196 case GDK_Delete
: key_code
= WXK_DELETE
; break;
197 case GDK_Home
: key_code
= WXK_HOME
; break;
198 case GDK_Left
: key_code
= WXK_LEFT
; break;
199 case GDK_Up
: key_code
= WXK_UP
; break;
200 case GDK_Right
: key_code
= WXK_RIGHT
; break;
201 case GDK_Down
: key_code
= WXK_DOWN
; break;
202 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
203 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
204 case GDK_Next
: key_code
= WXK_NEXT
; break;
205 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
206 case GDK_End
: key_code
= WXK_END
; break;
207 case GDK_Begin
: key_code
= WXK_HOME
; break;
208 case GDK_Select
: key_code
= WXK_SELECT
; break;
209 case GDK_Print
: key_code
= WXK_PRINT
; break;
210 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
211 case GDK_Insert
: key_code
= WXK_INSERT
; break;
212 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
213 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
214 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
215 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
216 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
217 case GDK_KP_Up
: key_code
= WXK_UP
; break;
218 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
219 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
220 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
221 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
222 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
223 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
224 case GDK_KP_End
: key_code
= WXK_END
; break;
225 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
226 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
227 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
228 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
229 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
230 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
231 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
232 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
233 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
234 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
235 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
236 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
237 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
238 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
239 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
240 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
241 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
242 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
243 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
244 case GDK_F1
: key_code
= WXK_F1
; break;
245 case GDK_F2
: key_code
= WXK_F2
; break;
246 case GDK_F3
: key_code
= WXK_F3
; break;
247 case GDK_F4
: key_code
= WXK_F4
; break;
248 case GDK_F5
: key_code
= WXK_F5
; break;
249 case GDK_F6
: key_code
= WXK_F6
; break;
250 case GDK_F7
: key_code
= WXK_F7
; break;
251 case GDK_F8
: key_code
= WXK_F8
; break;
252 case GDK_F9
: key_code
= WXK_F9
; break;
253 case GDK_F10
: key_code
= WXK_F10
; break;
254 case GDK_F11
: key_code
= WXK_F11
; break;
255 case GDK_F12
: key_code
= WXK_F12
; break;
258 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
259 key_code
= gdk_event
->keyval
;
263 if (!key_code
) return FALSE
;
265 wxKeyEvent
event( wxEVT_CHAR
);
266 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
267 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
268 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
269 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
270 event
.m_keyCode
= key_code
;
273 event
.SetEventObject( win
);
275 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
279 wxWindow
*ancestor
= win
;
282 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
285 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
286 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
289 ancestor
= ancestor
->GetParent();
295 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
296 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
302 //-----------------------------------------------------------------------------
303 // "button_press_event"
304 //-----------------------------------------------------------------------------
306 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
308 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
310 if (g_blockEventsOnDrag
) return TRUE
;
314 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
316 gtk_widget_grab_focus (win
->m_wxwindow
);
319 printf( "GrabFocus from " );
320 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
321 printf( win->GetClassInfo()->GetClassName() );
328 if (!win
->HasVMT()) return TRUE
;
331 printf( "OnButtonPress from " );
332 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
333 printf( win->GetClassInfo()->GetClassName() );
337 wxEventType event_type
= wxEVT_LEFT_DOWN
;
339 if (gdk_event
->button
== 1)
341 switch (gdk_event
->type
)
343 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
344 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
348 else if (gdk_event
->button
== 2)
350 switch (gdk_event
->type
)
352 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
353 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
357 else if (gdk_event
->button
== 3)
359 switch (gdk_event
->type
)
361 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
362 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
367 wxMouseEvent
event( event_type
);
368 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
369 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
370 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
371 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
372 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
373 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
374 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
376 event
.m_x
= (long)gdk_event
->x
;
377 event
.m_y
= (long)gdk_event
->y
;
379 // Some control don't have their own X window and thus cannot get
384 wxNode
*node
= win
->GetChildren()->First();
387 wxWindow
*child
= (wxWindow
*)node
->Data();
388 if ((child
->m_x
<= event
.m_x
) &&
389 (child
->m_y
<= event
.m_y
) &&
390 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
391 (child
->m_y
+child
->m_height
>= event
.m_y
))
394 event
.m_x
-= child
->m_x
;
395 event
.m_y
-= child
->m_y
;
402 event
.SetEventObject( win
);
404 if (win
->GetEventHandler()->ProcessEvent( event
))
405 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
410 //-----------------------------------------------------------------------------
411 // "button_release_event"
412 //-----------------------------------------------------------------------------
414 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
416 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
418 if (g_blockEventsOnDrag
) return TRUE
;
420 if (!win
->HasVMT()) return TRUE
;
423 printf( "OnButtonRelease from " );
424 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
425 printf( win->GetClassInfo()->GetClassName() );
429 wxEventType event_type
= wxEVT_NULL
;
431 switch (gdk_event
->button
)
433 case 1: event_type
= wxEVT_LEFT_UP
; break;
434 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
435 case 3: event_type
= wxEVT_RIGHT_UP
; break;
438 wxMouseEvent
event( event_type
);
439 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
440 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
441 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
442 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
443 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
444 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
445 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
446 event
.m_x
= (long)gdk_event
->x
;
447 event
.m_y
= (long)gdk_event
->y
;
449 // Some control don't have their own X window and thus cannot get
454 wxNode
*node
= win
->GetChildren()->First();
457 wxWindow
*child
= (wxWindow
*)node
->Data();
458 if ((child
->m_x
<= event
.m_x
) &&
459 (child
->m_y
<= event
.m_y
) &&
460 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
461 (child
->m_y
+child
->m_height
>= event
.m_y
))
464 event
.m_x
-= child
->m_x
;
465 event
.m_y
-= child
->m_y
;
472 event
.SetEventObject( win
);
474 if (win
->GetEventHandler()->ProcessEvent( event
))
475 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
480 //-----------------------------------------------------------------------------
481 // "motion_notify_event"
482 //-----------------------------------------------------------------------------
484 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
486 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
488 if (g_blockEventsOnDrag
) return TRUE
;
490 if (!win
->HasVMT()) return TRUE
;
493 printf( "OnMotion from " );
494 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
495 printf( win->GetClassInfo()->GetClassName() );
499 wxMouseEvent
event( wxEVT_MOTION
);
500 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
501 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
502 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
503 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
504 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
505 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
506 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
508 event
.m_x
= (long)gdk_event
->x
;
509 event
.m_y
= (long)gdk_event
->y
;
511 // Some control don't have their own X window and thus cannot get
516 wxNode
*node
= win
->GetChildren()->First();
519 wxWindow
*child
= (wxWindow
*)node
->Data();
520 if ((child
->m_x
<= event
.m_x
) &&
521 (child
->m_y
<= event
.m_y
) &&
522 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
523 (child
->m_y
+child
->m_height
>= event
.m_y
))
526 event
.m_x
-= child
->m_x
;
527 event
.m_y
-= child
->m_y
;
534 event
.SetEventObject( win
);
536 if (win
->GetEventHandler()->ProcessEvent( event
))
537 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
542 //-----------------------------------------------------------------------------
544 //-----------------------------------------------------------------------------
546 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
548 if (g_blockEventsOnDrag
) return TRUE
;
551 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
553 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
555 printf( "SetFocus flag from " );
556 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
557 printf( win->GetClassInfo()->GetClassName() );
563 if (!win
->HasVMT()) return TRUE
;
566 printf( "OnSetFocus from " );
567 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
568 printf( win->GetClassInfo()->GetClassName() );
570 printf( WXSTRINGCAST win->GetLabel() );
574 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
575 event
.SetEventObject( win
);
577 if (win
->GetEventHandler()->ProcessEvent( event
))
578 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
583 //-----------------------------------------------------------------------------
585 //-----------------------------------------------------------------------------
587 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
589 if (g_blockEventsOnDrag
) return TRUE
;
592 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
593 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
596 if (!win
->HasVMT()) return TRUE
;
599 printf( "OnKillFocus from " );
600 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
601 printf( win->GetClassInfo()->GetClassName() );
605 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
606 event
.SetEventObject( win
);
608 if (win
->GetEventHandler()->ProcessEvent( event
))
609 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
614 //-----------------------------------------------------------------------------
615 // "enter_notify_event"
616 //-----------------------------------------------------------------------------
618 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
620 if (widget
->window
!= gdk_event
->window
) return TRUE
;
622 if (g_blockEventsOnDrag
) return TRUE
;
624 if (!win
->HasVMT()) return TRUE
;
627 printf( "OnEnter from " );
628 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
629 printf( win->GetClassInfo()->GetClassName() );
633 if ((widget
->window
) && (win
->m_cursor
))
634 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
636 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
637 event
.SetEventObject( win
);
639 if (win
->GetEventHandler()->ProcessEvent( event
))
640 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
645 //-----------------------------------------------------------------------------
646 // "leave_notify_event"
647 //-----------------------------------------------------------------------------
649 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
651 if (widget
->window
!= gdk_event
->window
) return TRUE
;
653 if (g_blockEventsOnDrag
) return TRUE
;
655 if (!win
->HasVMT()) return TRUE
;
658 printf( "OnLeave from " );
659 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
660 printf( win->GetClassInfo()->GetClassName() );
664 if ((widget
->window
) && (win
->m_cursor
))
665 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
667 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
668 event
.SetEventObject( win
);
670 if (win
->GetEventHandler()->ProcessEvent( event
))
671 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
676 //-----------------------------------------------------------------------------
677 // "value_changed" from m_vAdjust
678 //-----------------------------------------------------------------------------
680 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
682 if (g_blockEventsOnDrag
) return;
685 printf( "OnVScroll from " );
686 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
687 printf( win->GetClassInfo()->GetClassName() );
691 if (!win
->HasVMT()) return;
693 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
694 if (fabs(diff
) < 0.2) return;
696 wxEventType command
= wxEVT_NULL
;
698 float line_step
= win
->m_vAdjust
->step_increment
;
699 float page_step
= win
->m_vAdjust
->page_increment
;
701 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
702 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
703 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
704 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
705 else command
= wxEVT_SCROLL_THUMBTRACK
;
707 int value
= (int)(win
->m_vAdjust
->value
+0.5);
709 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
710 event
.SetEventObject( win
);
711 win
->GetEventHandler()->ProcessEvent( event
);
714 //-----------------------------------------------------------------------------
715 // "value_changed" from m_hAdjust
716 //-----------------------------------------------------------------------------
718 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
720 if (g_blockEventsOnDrag
) return;
723 printf( "OnHScroll from " );
724 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
725 printf( win->GetClassInfo()->GetClassName() );
729 if (!win
->HasVMT()) return;
731 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
732 if (fabs(diff
) < 0.2) return;
734 wxEventType command
= wxEVT_NULL
;
736 float line_step
= win
->m_hAdjust
->step_increment
;
737 float page_step
= win
->m_hAdjust
->page_increment
;
739 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
740 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
741 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
742 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
743 else command
= wxEVT_SCROLL_THUMBTRACK
;
745 int value
= (int)(win
->m_hAdjust
->value
+0.5);
747 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
748 event
.SetEventObject( win
);
749 win
->GetEventHandler()->ProcessEvent( event
);
752 //-----------------------------------------------------------------------------
753 // "changed" from m_vAdjust
754 //-----------------------------------------------------------------------------
756 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
758 if (g_blockEventsOnDrag
) return;
761 printf( "OnVScroll change from " );
762 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
763 printf( win->GetClassInfo()->GetClassName() );
767 if (!win
->HasVMT()) return;
769 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
770 int value
= (int)(win
->m_vAdjust
->value
+0.5);
772 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
773 event
.SetEventObject( win
);
774 win
->GetEventHandler()->ProcessEvent( event
);
777 //-----------------------------------------------------------------------------
778 // "changed" from m_hAdjust
779 //-----------------------------------------------------------------------------
781 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
783 if (g_blockEventsOnDrag
) return;
786 printf( "OnHScroll change from " );
787 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
788 printf( win->GetClassInfo()->GetClassName() );
792 if (!win
->HasVMT()) return;
794 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
795 int value
= (int)(win
->m_hAdjust
->value
+0.5);
797 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
798 event
.SetEventObject( win
);
799 win
->GetEventHandler()->ProcessEvent( event
);
802 //-----------------------------------------------------------------------------
803 // "button_press_event" from scrollbar
804 //-----------------------------------------------------------------------------
806 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
808 if (gdk_event
->window
!= widget
->slider
) return FALSE
;
810 win
->m_isScrolling
= TRUE
;
815 //-----------------------------------------------------------------------------
816 // "button_release_event" from scrollbar
817 //-----------------------------------------------------------------------------
819 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
821 if (gdk_event
->window
!= widget
->slider
) return FALSE
;
823 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(win
->m_widget
);
825 if (widget
== GTK_RANGE(s_window
->vscrollbar
))
826 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
828 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
830 win
->m_isScrolling
= FALSE
;
835 //-----------------------------------------------------------------------------
836 // "drop_data_available_event"
837 //-----------------------------------------------------------------------------
839 static void gtk_window_drop_callback( GtkWidget
*widget
, GdkEvent
*event
, wxWindow
*win
)
841 if (!win
->HasVMT()) return;
843 if (win
->GetDropTarget())
847 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
848 win
->GetDropTarget()->Drop( event
, x
, y
);
852 g_free (event->dropdataavailable.data);
853 g_free (event->dropdataavailable.data_type);
857 //-----------------------------------------------------------------------------
859 //-----------------------------------------------------------------------------
861 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
863 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
864 EVT_SIZE(wxWindow::OnSize
)
865 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
866 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
867 EVT_IDLE(wxWindow::OnIdle
)
872 m_widget
= (GtkWidget
*) NULL
;
873 m_wxwindow
= (GtkWidget
*) NULL
;
874 m_parent
= (wxWindow
*) NULL
;
875 m_children
.DeleteContents( FALSE
);
885 m_eventHandler
= this;
886 m_windowValidator
= (wxValidator
*) NULL
;
888 m_cursor
= (wxCursor
*) NULL
;
889 m_font
= *wxSWISS_FONT
;
891 m_windowName
= "noname";
892 m_constraints
= (wxLayoutConstraints
*) NULL
;
893 m_constraintsInvolvedIn
= (wxList
*) NULL
;
894 m_windowSizer
= (wxSizer
*) NULL
;
895 m_sizerParent
= (wxWindow
*) NULL
;
896 m_autoLayout
= FALSE
;
900 m_hasScrolling
= FALSE
;
901 m_isScrolling
= FALSE
;
902 m_hAdjust
= (GtkAdjustment
*) NULL
;
903 m_vAdjust
= (GtkAdjustment
*) NULL
;
904 m_oldHorizontalPos
= 0.0;
905 m_oldVerticalPos
= 0.0;
908 m_pDropTarget
= (wxDropTarget
*) NULL
;
910 m_hasOwnStyle
= FALSE
;
913 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
914 const wxPoint
&pos
, const wxSize
&size
,
915 long style
, const wxString
&name
)
921 m_cursor
= (wxCursor
*) NULL
;
923 PreCreation( parent
, id
, pos
, size
, style
, name
);
925 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
926 m_hasScrolling
= TRUE
;
928 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(m_widget
);
930 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_press_event",
931 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
933 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_release_event",
934 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
936 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
937 scroll_class
->scrollbar_spacing
= 0;
939 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
941 m_oldHorizontalPos
= 0.0;
942 m_oldVerticalPos
= 0.0;
944 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
945 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
947 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
948 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
949 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
950 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
952 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
953 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
954 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
955 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
957 GtkViewport
*viewport
= GTK_VIEWPORT(s_window
->viewport
);
959 if (m_windowStyle
& wxRAISED_BORDER
)
961 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
963 else if (m_windowStyle
& wxSUNKEN_BORDER
)
965 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
969 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
972 m_wxwindow
= gtk_myfixed_new();
974 if (m_wxwindow
) GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
976 if (m_windowStyle
& wxTAB_TRAVERSAL
== wxTAB_TRAVERSAL
)
977 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
979 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
981 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
983 // shut the viewport up
984 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
985 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
987 // I _really_ don't want scrollbars in the beginning
988 m_vAdjust
->lower
= 0.0;
989 m_vAdjust
->upper
= 1.0;
990 m_vAdjust
->value
= 0.0;
991 m_vAdjust
->step_increment
= 1.0;
992 m_vAdjust
->page_increment
= 1.0;
993 m_vAdjust
->page_size
= 5.0;
994 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
995 m_hAdjust
->lower
= 0.0;
996 m_hAdjust
->upper
= 1.0;
997 m_hAdjust
->value
= 0.0;
998 m_hAdjust
->step_increment
= 1.0;
999 m_hAdjust
->page_increment
= 1.0;
1000 m_hAdjust
->page_size
= 5.0;
1001 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1003 gtk_widget_show( m_wxwindow
);
1012 wxWindow::~wxWindow(void)
1016 if (m_pDropTarget
) delete m_pDropTarget
;
1018 if (m_parent
) m_parent
->RemoveChild( this );
1019 if (m_widget
) Show( FALSE
);
1023 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
1025 if (m_widget
) gtk_widget_destroy( m_widget
);
1029 DeleteRelatedConstraints();
1032 // This removes any dangling pointers to this window
1033 // in other windows' constraintsInvolvedIn lists.
1034 UnsetConstraints(m_constraints
);
1035 delete m_constraints
;
1036 m_constraints
= (wxLayoutConstraints
*) NULL
;
1040 delete m_windowSizer
;
1041 m_windowSizer
= (wxSizer
*) NULL
;
1043 // If this is a child of a sizer, remove self from parent
1044 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
1046 // Just in case the window has been Closed, but
1047 // we're then deleting immediately: don't leave
1048 // dangling pointers.
1049 wxPendingDelete
.DeleteObject(this);
1051 // Just in case we've loaded a top-level window via
1052 // wxWindow::LoadNativeDialog but we weren't a dialog
1054 wxTopLevelWindows
.DeleteObject(this);
1056 if (m_windowValidator
) delete m_windowValidator
;
1059 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1060 const wxPoint
&pos
, const wxSize
&size
,
1061 long style
, const wxString
&name
)
1063 if (m_needParent
&& (parent
== NULL
))
1064 wxFatalError( "Need complete parent.", name
);
1066 m_widget
= (GtkWidget
*) NULL
;
1069 m_children
.DeleteContents( FALSE
);
1073 if (m_width
== -1) m_width
= 20;
1075 if (m_height
== -1) m_height
= 20;
1081 m_eventHandler
= this;
1084 if (m_cursor
== NULL
)
1085 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1086 m_font
= *wxSWISS_FONT
;
1087 m_backgroundColour
= wxWHITE
;
1088 m_foregroundColour
= wxBLACK
;
1089 m_windowStyle
= style
;
1090 m_windowName
= name
;
1091 m_constraints
= (wxLayoutConstraints
*) NULL
;
1092 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1093 m_windowSizer
= (wxSizer
*) NULL
;
1094 m_sizerParent
= (wxWindow
*) NULL
;
1095 m_autoLayout
= FALSE
;
1096 m_hasScrolling
= FALSE
;
1097 m_isScrolling
= FALSE
;
1098 m_pDropTarget
= (wxDropTarget
*) NULL
;
1100 m_windowValidator
= (wxValidator
*) NULL
;
1101 m_hasOwnStyle
= FALSE
;
1104 void wxWindow::PostCreation(void)
1106 if (m_parent
) m_parent
->AddChild( this );
1110 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1111 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1113 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1114 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1117 ConnectWidget( GetConnectWidget() );
1119 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1123 gtk_widget_realize( m_wxwindow
);
1124 gdk_gc_set_exposures( m_wxwindow
->style
->fg_gc
[0], TRUE
);
1127 SetCursor( *wxSTANDARD_CURSOR
);
1132 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1134 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1135 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1137 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1138 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1140 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1141 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1143 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1144 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1146 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1147 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1149 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1150 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1152 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1153 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1155 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1156 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1159 bool wxWindow::HasVMT(void)
1164 bool wxWindow::Close( bool force
)
1166 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1168 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1169 event
.SetEventObject(this);
1170 event
.SetForce(force
);
1172 return GetEventHandler()->ProcessEvent(event
);
1175 bool wxWindow::Destroy(void)
1177 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1184 bool wxWindow::DestroyChildren(void)
1189 while ((node
= GetChildren()->First()) != (wxNode
*)NULL
)
1192 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1195 if (GetChildren()->Member(child
)) delete node
;
1202 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1204 // are we to set fonts here ?
1207 void wxWindow::ImplementSetSize(void)
1209 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1210 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1211 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_minWidth
;
1212 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_minHeight
;
1213 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1216 void wxWindow::ImplementSetPosition(void)
1218 if (IS_KIND_OF(this,wxFrame
) || IS_KIND_OF(this,wxDialog
))
1220 if ((m_x
!= -1) || (m_y
!= -1))
1221 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
1227 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1231 if ((m_parent
) && (m_parent
->m_wxwindow
))
1232 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
, m_y
);
1234 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1237 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1239 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1241 if (m_resizing
) return; // I don't like recursions
1249 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1251 if (newX
== -1) newX
= m_x
;
1252 if (newY
== -1) newY
= m_y
;
1253 if (newW
== -1) newW
= m_width
;
1254 if (newH
== -1) newH
= m_height
;
1257 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1259 if (newW
== -1) newW
= 80;
1262 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1264 if (newH
== -1) newH
= 26;
1267 if ((m_x
!= newX
) || (m_y
!= newY
) || (!m_sizeSet
))
1271 ImplementSetPosition();
1273 if ((m_width
!= newW
) || (m_height
!= newH
) || (!m_sizeSet
))
1281 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1282 event
.SetEventObject( this );
1283 ProcessEvent( event
);
1288 void wxWindow::SetSize( int width
, int height
)
1290 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1293 void wxWindow::Move( int x
, int y
)
1295 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1298 void wxWindow::GetSize( int *width
, int *height
) const
1300 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1302 if (width
) (*width
) = m_width
;
1303 if (height
) (*height
) = m_height
;
1306 void wxWindow::SetClientSize( int width
, int height
)
1308 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1312 SetSize( width
, height
);
1319 if (!m_hasScrolling
)
1322 do we have sunken dialogs ?
1324 GtkStyleClass *window_class = m_wxwindow->style->klass;
1326 dw += 2 * window_class->xthickness;
1327 dh += 2 * window_class->ythickness;
1332 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1333 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1335 GtkWidget
*viewport
= scroll_window
->viewport
;
1336 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1338 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1339 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1341 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1342 (m_windowStyle
& wxSUNKEN_BORDER
))
1344 dw
+= 2 * viewport_class
->xthickness
;
1345 dh
+= 2 * viewport_class
->ythickness
;
1348 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1350 dw
+= vscrollbar
->allocation
.width
;
1351 dw
+= scroll_class
->scrollbar_spacing
;
1354 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1356 dh
+= hscrollbar
->allocation
.height
;
1357 dw
+= scroll_class
->scrollbar_spacing
;
1361 SetSize( width
+dw
, height
+dh
);
1365 void wxWindow::GetClientSize( int *width
, int *height
) const
1367 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1371 if (width
) (*width
) = m_width
;
1372 if (height
) (*height
) = m_height
;
1379 if (!m_hasScrolling
)
1382 do we have sunken dialogs ?
1384 GtkStyleClass *window_class = m_wxwindow->style->klass;
1386 dw += 2 * window_class->xthickness;
1387 dh += 2 * window_class->ythickness;
1392 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1393 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1395 GtkWidget
*viewport
= scroll_window
->viewport
;
1396 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1398 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1399 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1401 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1402 (m_windowStyle
& wxSUNKEN_BORDER
))
1404 dw
+= 2 * viewport_class
->xthickness
;
1405 dh
+= 2 * viewport_class
->ythickness
;
1408 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1410 // dw += vscrollbar->allocation.width;
1411 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1412 dw
+= scroll_class
->scrollbar_spacing
;
1415 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1417 // dh += hscrollbar->allocation.height;
1419 dh
+= scroll_class
->scrollbar_spacing
;
1423 if (width
) (*width
) = m_width
- dw
;
1424 if (height
) (*height
) = m_height
- dh
;
1428 void wxWindow::GetPosition( int *x
, int *y
) const
1430 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1436 void wxWindow::ClientToScreen( int *x
, int *y
)
1438 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1440 GdkWindow
*source
= (GdkWindow
*) NULL
;
1442 source
= m_wxwindow
->window
;
1444 source
= m_widget
->window
;
1448 gdk_window_get_origin( source
, &org_x
, &org_y
);
1452 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1454 org_x
+= m_widget
->allocation
.x
;
1455 org_y
+= m_widget
->allocation
.y
;
1463 void wxWindow::ScreenToClient( int *x
, int *y
)
1465 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1467 GdkWindow
*source
= (GdkWindow
*) NULL
;
1469 source
= m_wxwindow
->window
;
1471 source
= m_widget
->window
;
1475 gdk_window_get_origin( source
, &org_x
, &org_y
);
1479 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1481 org_x
+= m_widget
->allocation
.x
;
1482 org_y
+= m_widget
->allocation
.y
;
1490 void wxWindow::Centre( int direction
)
1492 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1494 if (IS_KIND_OF(this,wxDialog
) || IS_KIND_OF(this,wxFrame
))
1496 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (gdk_screen_width () - m_width
) / 2;
1497 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (gdk_screen_height () - m_height
) / 2;
1498 ImplementSetPosition();
1506 m_parent
->GetSize( &p_w
, &p_h
);
1507 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (p_w
- m_width
) / 2;
1508 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (p_h
- m_height
) / 2;
1509 ImplementSetPosition();
1514 void wxWindow::Fit(void)
1516 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1520 wxNode
*node
= GetChildren()->First();
1523 wxWindow
*win
= (wxWindow
*)node
->Data();
1525 win
->GetPosition(&wx
, &wy
);
1526 win
->GetSize(&ww
, &wh
);
1527 if ( wx
+ ww
> maxX
)
1529 if ( wy
+ wh
> maxY
)
1532 node
= node
->Next();
1534 SetClientSize(maxX
+ 5, maxY
+ 10);
1537 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1539 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1547 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1549 //if (GetAutoLayout()) Layout();
1552 bool wxWindow::Show( bool show
)
1554 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1557 gtk_widget_show( m_widget
);
1559 gtk_widget_hide( m_widget
);
1564 void wxWindow::Enable( bool enable
)
1566 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1568 m_isEnabled
= enable
;
1569 gtk_widget_set_sensitive( m_widget
, enable
);
1570 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1573 int wxWindow::GetCharHeight(void) const
1575 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1579 wxFAIL_MSG( "invalid font" );
1583 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1584 return font
->ascent
+ font
->descent
;
1587 int wxWindow::GetCharWidth(void) const
1589 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1593 wxFAIL_MSG( "invalid font" );
1597 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1598 return gdk_string_width( font
, "H" );
1601 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1602 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1604 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1606 wxFont fontToUse
= m_font
;
1607 if (theFont
) fontToUse
= *theFont
;
1609 if (!fontToUse
.Ok())
1611 wxFAIL_MSG( "invalid font" );
1614 wxASSERT_MSG( (m_font
.Ok()), "invalid font" );
1616 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1617 if (x
) (*x
) = gdk_string_width( font
, string
);
1618 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1619 if (descent
) (*descent
) = font
->descent
;
1620 if (externalLeading
) (*externalLeading
) = 0; // ??
1623 void wxWindow::MakeModal( bool modal
)
1626 // Disable all other windows
1627 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1629 wxNode
*node
= wxTopLevelWindows
.First();
1632 wxWindow
*win
= (wxWindow
*)node
->Data();
1634 win
->Enable(!modal
);
1636 node
= node
->Next();
1641 void wxWindow::SetFocus(void)
1643 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1645 GtkWidget
*connect_widget
= GetConnectWidget();
1648 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) && !GTK_WIDGET_HAS_FOCUS (connect_widget
) )
1650 gtk_widget_grab_focus (connect_widget
);
1655 bool wxWindow::OnClose(void)
1660 void wxWindow::AddChild( wxWindow
*child
)
1662 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1663 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window need client area" );
1664 wxASSERT_MSG( (child
!= NULL
), "invalid child" );
1665 wxASSERT_MSG( (child
->m_widget
!= NULL
), "invalid child" );
1667 // Addchild is (often) called before the program
1668 // has left the parents constructor so that no
1669 // virtual tables work yet. The approach below
1670 // practically imitates virtual tables, i.e. it
1671 // implements a different AddChild() behaviour
1672 // for wxFrame, wxDialog, wxWindow and
1673 // wxMDIParentFrame.
1675 // wxFrame and wxDialog as children aren't placed into the parents
1677 if (( IS_KIND_OF(child
,wxFrame
) || IS_KIND_OF(child
,wxDialog
) ) &&
1678 (!IS_KIND_OF(child
,wxMDIChildFrame
)))
1680 m_children
.Append( child
);
1682 if ((child
->m_x
!= -1) && (child
->m_y
!= -1))
1683 gtk_widget_set_uposition( child
->m_widget
, child
->m_x
, child
->m_y
);
1688 // In the case of an wxMDIChildFrame descendant, we use the
1689 // client windows's AddChild()
1691 if (IS_KIND_OF(this,wxMDIParentFrame
))
1693 if (IS_KIND_OF(child
,wxMDIChildFrame
))
1695 wxMDIClientWindow
*client
= ((wxMDIParentFrame
*)this)->GetClientWindow();
1698 client
->AddChild( child
);
1704 // wxNotebook is very special, so it has a private AddChild()
1706 if (IS_KIND_OF(this,wxNotebook
))
1708 wxNotebook
*tab
= (wxNotebook
*)this;
1709 tab
->AddChild( child
);
1713 // wxFrame has a private AddChild
1715 if (IS_KIND_OF(this,wxFrame
) && !IS_KIND_OF(this,wxMDIChildFrame
))
1717 wxFrame
*frame
= (wxFrame
*)this;
1718 frame
->AddChild( child
);
1724 m_children
.Append( child
);
1725 if (m_wxwindow
) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), child
->m_widget
,
1726 child
->m_x
, child
->m_y
);
1728 gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height
);
1731 wxList
*wxWindow::GetChildren(void)
1733 return (&m_children
);
1736 void wxWindow::RemoveChild( wxWindow
*child
)
1739 GetChildren()->DeleteObject( child
);
1740 child
->m_parent
= (wxWindow
*) NULL
;
1743 void wxWindow::SetReturnCode( int retCode
)
1745 m_retCode
= retCode
;
1748 int wxWindow::GetReturnCode(void)
1753 void wxWindow::Raise(void)
1755 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1757 if (m_widget
) gdk_window_raise( m_widget
->window
);
1760 void wxWindow::Lower(void)
1762 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1764 if (m_widget
) gdk_window_lower( m_widget
->window
);
1767 wxEvtHandler
*wxWindow::GetEventHandler(void)
1769 return m_eventHandler
;
1772 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
1774 m_eventHandler
= handler
;
1777 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
1779 handler
->SetNextHandler(GetEventHandler());
1780 SetEventHandler(handler
);
1783 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
1785 if (GetEventHandler())
1787 wxEvtHandler
*handlerA
= GetEventHandler();
1788 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
1789 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
1790 SetEventHandler(handlerB
);
1794 return (wxEvtHandler
*) NULL
;
1800 return (wxEvtHandler
*) NULL
;
1803 wxValidator
*wxWindow::GetValidator(void)
1805 return m_windowValidator
;
1808 void wxWindow::SetValidator( const wxValidator
& validator
)
1810 if (m_windowValidator
) delete m_windowValidator
;
1811 m_windowValidator
= validator
.Clone();
1812 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
1815 bool wxWindow::IsBeingDeleted(void)
1820 void wxWindow::SetId( wxWindowID id
)
1825 wxWindowID
wxWindow::GetId(void)
1830 void wxWindow::SetCursor( const wxCursor
&cursor
)
1832 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1834 if (m_cursor
== NULL
)
1836 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1837 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1842 if (*((wxCursor
*)&cursor
) == m_cursor
) return;
1847 *m_cursor
= *wxSTANDARD_CURSOR
;
1850 if ((m_widget
) && (m_widget
->window
))
1851 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
1853 if ((m_wxwindow
) && (m_wxwindow
->window
))
1854 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
1857 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
1859 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1861 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
1864 gdk_window_clear_area( m_wxwindow
->window
,
1878 GetClientSize( &w
, &h
);
1880 GdkRectangle gdk_rect
;
1884 gdk_rect
.height
= h
;
1885 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1890 GdkRectangle gdk_rect
;
1891 gdk_rect
.x
= rect
->x
;
1892 gdk_rect
.y
= rect
->y
;
1893 gdk_rect
.width
= rect
->width
;
1894 gdk_rect
.height
= rect
->height
;
1897 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1899 gtk_widget_draw( m_widget
, &gdk_rect
);
1903 wxRegion
wxWindow::GetUpdateRegion() const
1905 return m_updateRegion
;
1908 bool wxWindow::IsExposed( int x
, int y
) const
1910 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
1913 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
1915 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
1918 bool wxWindow::IsExposed( const wxPoint
& pt
) const
1920 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
1923 bool wxWindow::IsExposed( const wxRect
& rect
) const
1925 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
1928 void wxWindow::Clear(void)
1930 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1932 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
1935 wxColour
wxWindow::GetBackgroundColour(void) const
1937 return m_backgroundColour
;
1940 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
1942 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1944 m_backgroundColour
= colour
;
1947 m_backgroundColour
.CalcPixel( m_wxwindow
->style
->colormap
);
1948 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
1949 gdk_window_clear( m_wxwindow
->window
);
1954 wxColour
wxWindow::GetForegroundColour(void) const
1956 return m_foregroundColour
;
1959 void wxWindow::SetForegroundColour( const wxColour
&colour
)
1961 m_foregroundColour
= colour
;
1964 bool wxWindow::Validate(void)
1966 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1968 wxNode
*node
= GetChildren()->First();
1971 wxWindow
*child
= (wxWindow
*)node
->Data();
1972 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
1974 node
= node
->Next();
1979 bool wxWindow::TransferDataToWindow(void)
1981 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1983 wxNode
*node
= GetChildren()->First();
1986 wxWindow
*child
= (wxWindow
*)node
->Data();
1987 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
1988 !child
->GetValidator()->TransferToWindow() )
1990 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
1993 node
= node
->Next();
1998 bool wxWindow::TransferDataFromWindow(void)
2000 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2002 wxNode
*node
= GetChildren()->First();
2005 wxWindow
*child
= (wxWindow
*)node
->Data();
2006 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
2008 node
= node
->Next();
2013 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
2015 m_acceleratorTable
= accel
;
2018 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
2020 TransferDataToWindow();
2023 void wxWindow::InitDialog(void)
2025 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2027 wxInitDialogEvent
event(GetId());
2028 event
.SetEventObject( this );
2029 GetEventHandler()->ProcessEvent(event
);
2032 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2034 menu
->SetInvokingWindow( win
);
2035 wxNode
*node
= menu
->m_items
.First();
2038 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2039 if (menuitem
->IsSubMenu())
2040 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2041 node
= node
->Next();
2045 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
2047 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2049 SetInvokingWindow( menu
, this );
2050 gtk_menu_popup( GTK_MENU(menu
->m_menu
), (GtkWidget
*) NULL
, (GtkWidget
*) NULL
, (GtkMenuPositionFunc
) NULL
, NULL
, 0, 0 );
2054 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2056 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2058 GtkWidget
*dnd_widget
= GetConnectWidget();
2060 DisconnectDnDWidget( dnd_widget
);
2062 if (m_pDropTarget
) delete m_pDropTarget
;
2063 m_pDropTarget
= dropTarget
;
2065 ConnectDnDWidget( dnd_widget
);
2068 wxDropTarget
*wxWindow::GetDropTarget() const
2070 return m_pDropTarget
;
2073 void wxWindow::ConnectDnDWidget( GtkWidget
*widget
)
2075 if (!m_pDropTarget
) return;
2077 m_pDropTarget
->RegisterWidget( widget
);
2079 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
2080 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2083 void wxWindow::DisconnectDnDWidget( GtkWidget
*widget
)
2085 if (!m_pDropTarget
) return;
2087 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
2088 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2090 m_pDropTarget
->UnregisterWidget( widget
);
2093 GtkWidget
* wxWindow::GetConnectWidget(void)
2095 GtkWidget
*connect_widget
= m_widget
;
2096 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2098 return connect_widget
;
2101 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2103 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2104 return (window
== m_widget
->window
);
2107 void wxWindow::SetFont( const wxFont
&font
)
2109 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2111 if (((wxFont
*)&font
)->Ok())
2114 m_font
= *wxSWISS_FONT
;
2116 GtkStyle
*style
= (GtkStyle
*) NULL
;
2119 m_hasOwnStyle
= TRUE
;
2120 style
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2124 style
= gtk_widget_get_style( m_widget
);
2127 gdk_font_unref( style
->font
);
2128 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2130 gtk_widget_set_style( m_widget
, style
);
2133 wxFont
*wxWindow::GetFont(void)
2138 void wxWindow::SetWindowStyleFlag( long flag
)
2140 m_windowStyle
= flag
;
2143 long wxWindow::GetWindowStyleFlag(void) const
2145 return m_windowStyle
;
2148 void wxWindow::CaptureMouse(void)
2150 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2152 wxASSERT_MSG( (g_capturing
== FALSE
), "CaptureMouse called twice" );
2154 GtkWidget
*connect_widget
= GetConnectWidget();
2155 gtk_grab_add( connect_widget
);
2156 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
2158 (GDK_BUTTON_PRESS_MASK
|
2159 GDK_BUTTON_RELEASE_MASK
|
2160 GDK_POINTER_MOTION_MASK
),
2161 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
2165 void wxWindow::ReleaseMouse(void)
2167 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2169 wxASSERT_MSG( (g_capturing
== TRUE
), "ReleaseMouse called twice" );
2171 GtkWidget
*connect_widget
= GetConnectWidget();
2172 gtk_grab_remove( connect_widget
);
2173 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2174 g_capturing
= FALSE
;
2177 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2181 wxString
wxWindow::GetTitle(void) const
2183 return (wxString
&)m_windowName
;
2186 wxString
wxWindow::GetLabel(void) const
2191 void wxWindow::SetName( const wxString
&name
)
2193 m_windowName
= name
;
2196 wxString
wxWindow::GetName(void) const
2198 return (wxString
&)m_windowName
;
2201 bool wxWindow::IsShown(void) const
2206 bool wxWindow::IsRetained(void)
2211 wxWindow
*wxWindow::FindWindow( long id
)
2213 if (id
== m_windowId
) return this;
2214 wxNode
*node
= m_children
.First();
2217 wxWindow
*child
= (wxWindow
*)node
->Data();
2218 wxWindow
*res
= child
->FindWindow( id
);
2219 if (res
) return res
;
2220 node
= node
->Next();
2222 return (wxWindow
*) NULL
;
2225 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2227 if (name
== m_windowName
) return this;
2228 wxNode
*node
= m_children
.First();
2231 wxWindow
*child
= (wxWindow
*)node
->Data();
2232 wxWindow
*res
= child
->FindWindow( name
);
2233 if (res
) return res
;
2234 node
= node
->Next();
2236 return (wxWindow
*) NULL
;
2239 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2240 int range
, bool refresh
)
2242 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2244 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2246 if (!m_wxwindow
) return;
2248 if (orient
== wxHORIZONTAL
)
2250 float fpos
= (float)pos
;
2251 float frange
= (float)range
;
2252 float fthumb
= (float)thumbVisible
;
2254 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2255 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2257 SetScrollPos( orient
, pos
, refresh
);
2261 m_oldHorizontalPos
= fpos
;
2263 m_hAdjust
->lower
= 0.0;
2264 m_hAdjust
->upper
= frange
;
2265 m_hAdjust
->value
= fpos
;
2266 m_hAdjust
->step_increment
= 1.0;
2267 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2268 m_hAdjust
->page_size
= fthumb
;
2272 float fpos
= (float)pos
;
2273 float frange
= (float)range
;
2274 float fthumb
= (float)thumbVisible
;
2276 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2277 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2279 SetScrollPos( orient
, pos
, refresh
);
2283 m_oldVerticalPos
= fpos
;
2285 m_vAdjust
->lower
= 0.0;
2286 m_vAdjust
->upper
= frange
;
2287 m_vAdjust
->value
= fpos
;
2288 m_vAdjust
->step_increment
= 1.0;
2289 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2290 m_vAdjust
->page_size
= fthumb
;
2293 if (m_wxwindow
->window
)
2295 if (orient
== wxHORIZONTAL
)
2296 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2298 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2300 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2304 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2306 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2308 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2310 if (!m_wxwindow
) return;
2312 if (orient
== wxHORIZONTAL
)
2314 float fpos
= (float)pos
;
2315 m_oldHorizontalPos
= fpos
;
2317 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2318 m_hAdjust
->value
= fpos
;
2322 float fpos
= (float)pos
;
2323 m_oldVerticalPos
= fpos
;
2324 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2325 m_vAdjust
->value
= fpos
;
2330 if (m_wxwindow
->window
)
2332 if (orient
== wxHORIZONTAL
)
2333 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2335 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2340 int wxWindow::GetScrollThumb( int orient
) const
2342 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2344 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2346 if (!m_wxwindow
) return 0;
2348 if (orient
== wxHORIZONTAL
)
2349 return (int)(m_hAdjust
->page_size
+0.5);
2351 return (int)(m_vAdjust
->page_size
+0.5);
2354 int wxWindow::GetScrollPos( int orient
) const
2356 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2358 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2360 if (!m_wxwindow
) return 0;
2362 if (orient
== wxHORIZONTAL
)
2363 return (int)(m_hAdjust
->value
+0.5);
2365 return (int)(m_vAdjust
->value
+0.5);
2368 int wxWindow::GetScrollRange( int orient
) const
2370 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2372 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2374 if (!m_wxwindow
) return 0;
2376 if (orient
== wxHORIZONTAL
)
2377 return (int)(m_hAdjust
->upper
+0.5);
2379 return (int)(m_vAdjust
->upper
+0.5);
2382 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2384 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2386 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2388 if (!m_wxwindow
) return;
2392 GetClientSize( &cw
, &ch
);
2394 int w
= cw
- abs(dx
);
2395 int h
= ch
- abs(dy
);
2396 if ((h
< 0) || (w
< 0))
2403 if (dx
< 0) s_x
= -dx
;
2404 if (dy
< 0) s_y
= -dy
;
2407 if (dx
> 0) d_x
= dx
;
2408 if (dy
> 0) d_y
= dy
;
2409 gdk_window_copy_area( m_wxwindow
->window
, m_wxwindow
->style
->fg_gc
[0], d_x
, d_y
,
2410 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2413 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2414 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2415 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2416 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2418 Refresh( TRUE
, &rect
);
2421 //-------------------------------------------------------------------------------------
2423 //-------------------------------------------------------------------------------------
2425 wxLayoutConstraints
*wxWindow::GetConstraints(void) const
2427 return m_constraints
;
2430 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2434 UnsetConstraints(m_constraints
);
2435 delete m_constraints
;
2437 m_constraints
= constraints
;
2440 // Make sure other windows know they're part of a 'meaningful relationship'
2441 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2442 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2443 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2444 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2445 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2446 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2447 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2448 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2449 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2450 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2451 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2452 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2453 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2454 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2455 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2456 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2462 void wxWindow::SetAutoLayout( bool autoLayout
)
2464 m_autoLayout
= autoLayout
;
2467 bool wxWindow::GetAutoLayout(void) const
2469 return m_autoLayout
;
2472 wxSizer
*wxWindow::GetSizer(void) const
2474 return m_windowSizer
;
2477 void wxWindow::SetSizerParent( wxWindow
*win
)
2479 m_sizerParent
= win
;
2482 wxWindow
*wxWindow::GetSizerParent(void) const
2484 return m_sizerParent
;
2487 // This removes any dangling pointers to this window
2488 // in other windows' constraintsInvolvedIn lists.
2489 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2493 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2494 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2495 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2496 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2497 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2498 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2499 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2500 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2501 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2502 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2503 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2504 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2505 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2506 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2507 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2508 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2512 // Back-pointer to other windows we're involved with, so if we delete
2513 // this window, we must delete any constraints we're involved with.
2514 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2516 if (!m_constraintsInvolvedIn
)
2517 m_constraintsInvolvedIn
= new wxList
;
2518 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2519 m_constraintsInvolvedIn
->Append(otherWin
);
2522 // REMOVE back-pointer to other windows we're involved with.
2523 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2525 if (m_constraintsInvolvedIn
)
2526 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2529 // Reset any constraints that mention this window
2530 void wxWindow::DeleteRelatedConstraints(void)
2532 if (m_constraintsInvolvedIn
)
2534 wxNode
*node
= m_constraintsInvolvedIn
->First();
2537 wxWindow
*win
= (wxWindow
*)node
->Data();
2538 wxNode
*next
= node
->Next();
2539 wxLayoutConstraints
*constr
= win
->GetConstraints();
2541 // Reset any constraints involving this window
2544 constr
->left
.ResetIfWin((wxWindow
*)this);
2545 constr
->top
.ResetIfWin((wxWindow
*)this);
2546 constr
->right
.ResetIfWin((wxWindow
*)this);
2547 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2548 constr
->width
.ResetIfWin((wxWindow
*)this);
2549 constr
->height
.ResetIfWin((wxWindow
*)this);
2550 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2551 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2556 delete m_constraintsInvolvedIn
;
2557 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2561 void wxWindow::SetSizer(wxSizer
*sizer
)
2563 m_windowSizer
= sizer
;
2565 sizer
->SetSizerParent((wxWindow
*)this);
2572 bool wxWindow::Layout(void)
2574 if (GetConstraints())
2577 GetClientSize(&w
, &h
);
2578 GetConstraints()->width
.SetValue(w
);
2579 GetConstraints()->height
.SetValue(h
);
2582 // If top level (one sizer), evaluate the sizer's constraints.
2586 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2587 GetSizer()->LayoutPhase1(&noChanges
);
2588 GetSizer()->LayoutPhase2(&noChanges
);
2589 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2594 // Otherwise, evaluate child constraints
2595 ResetConstraints(); // Mark all constraints as unevaluated
2596 DoPhase(1); // Just one phase need if no sizers involved
2598 SetConstraintSizes(); // Recursively set the real window sizes
2604 // Do a phase of evaluating constraints:
2605 // the default behaviour. wxSizers may do a similar
2606 // thing, but also impose their own 'constraints'
2607 // and order the evaluation differently.
2608 bool wxWindow::LayoutPhase1(int *noChanges
)
2610 wxLayoutConstraints
*constr
= GetConstraints();
2613 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2619 bool wxWindow::LayoutPhase2(int *noChanges
)
2629 // Do a phase of evaluating child constraints
2630 bool wxWindow::DoPhase(int phase
)
2632 int noIterations
= 0;
2633 int maxIterations
= 500;
2637 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2641 wxNode
*node
= GetChildren()->First();
2644 wxWindow
*child
= (wxWindow
*)node
->Data();
2645 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2647 wxLayoutConstraints
*constr
= child
->GetConstraints();
2650 if (succeeded
.Member(child
))
2655 int tempNoChanges
= 0;
2656 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2657 noChanges
+= tempNoChanges
;
2660 succeeded
.Append(child
);
2665 node
= node
->Next();
2672 void wxWindow::ResetConstraints(void)
2674 wxLayoutConstraints
*constr
= GetConstraints();
2677 constr
->left
.SetDone(FALSE
);
2678 constr
->top
.SetDone(FALSE
);
2679 constr
->right
.SetDone(FALSE
);
2680 constr
->bottom
.SetDone(FALSE
);
2681 constr
->width
.SetDone(FALSE
);
2682 constr
->height
.SetDone(FALSE
);
2683 constr
->centreX
.SetDone(FALSE
);
2684 constr
->centreY
.SetDone(FALSE
);
2686 wxNode
*node
= GetChildren()->First();
2689 wxWindow
*win
= (wxWindow
*)node
->Data();
2690 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2691 win
->ResetConstraints();
2692 node
= node
->Next();
2696 // Need to distinguish between setting the 'fake' size for
2697 // windows and sizers, and setting the real values.
2698 void wxWindow::SetConstraintSizes(bool recurse
)
2700 wxLayoutConstraints
*constr
= GetConstraints();
2701 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2702 constr
->width
.GetDone() && constr
->height
.GetDone())
2704 int x
= constr
->left
.GetValue();
2705 int y
= constr
->top
.GetValue();
2706 int w
= constr
->width
.GetValue();
2707 int h
= constr
->height
.GetValue();
2709 // If we don't want to resize this window, just move it...
2710 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2711 (constr
->height
.GetRelationship() != wxAsIs
))
2713 // Calls Layout() recursively. AAAGH. How can we stop that.
2714 // Simply take Layout() out of non-top level OnSizes.
2715 SizerSetSize(x
, y
, w
, h
);
2724 char *windowClass
= this->GetClassInfo()->GetClassName();
2727 if (GetName() == "")
2728 winName
= _("unnamed");
2730 winName
= GetName();
2731 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2732 if (!constr
->left
.GetDone())
2733 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2734 if (!constr
->right
.GetDone())
2735 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2736 if (!constr
->width
.GetDone())
2737 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2738 if (!constr
->height
.GetDone())
2739 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2740 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2745 wxNode
*node
= GetChildren()->First();
2748 wxWindow
*win
= (wxWindow
*)node
->Data();
2749 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2750 win
->SetConstraintSizes();
2751 node
= node
->Next();
2756 // This assumes that all sizers are 'on' the same
2757 // window, i.e. the parent of this window.
2758 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2760 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2761 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2765 m_sizerParent
->GetPosition(&xp
, &yp
);
2766 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2771 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2775 TransformSizerToActual(&xx
, &yy
);
2776 SetSize(xx
, yy
, w
, h
);
2779 void wxWindow::SizerMove(int x
, int y
)
2783 TransformSizerToActual(&xx
, &yy
);
2787 // Only set the size/position of the constraint (if any)
2788 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2790 wxLayoutConstraints
*constr
= GetConstraints();
2795 constr
->left
.SetValue(x
);
2796 constr
->left
.SetDone(TRUE
);
2800 constr
->top
.SetValue(y
);
2801 constr
->top
.SetDone(TRUE
);
2805 constr
->width
.SetValue(w
);
2806 constr
->width
.SetDone(TRUE
);
2810 constr
->height
.SetValue(h
);
2811 constr
->height
.SetDone(TRUE
);
2816 void wxWindow::MoveConstraint(int x
, int y
)
2818 wxLayoutConstraints
*constr
= GetConstraints();
2823 constr
->left
.SetValue(x
);
2824 constr
->left
.SetDone(TRUE
);
2828 constr
->top
.SetValue(y
);
2829 constr
->top
.SetDone(TRUE
);
2834 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2836 wxLayoutConstraints
*constr
= GetConstraints();
2839 *w
= constr
->width
.GetValue();
2840 *h
= constr
->height
.GetValue();
2846 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2848 wxLayoutConstraints
*constr
= GetConstraints();
2851 *w
= constr
->width
.GetValue();
2852 *h
= constr
->height
.GetValue();
2855 GetClientSize(w
, h
);
2858 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2860 wxLayoutConstraints
*constr
= GetConstraints();
2863 *x
= constr
->left
.GetValue();
2864 *y
= constr
->top
.GetValue();
2870 bool wxWindow::AcceptsFocus() const
2872 return IsEnabled() && IsShown();
2875 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )