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 // "drop_data_available_event"
804 //-----------------------------------------------------------------------------
806 static void gtk_window_drop_callback( GtkWidget
*widget
, GdkEvent
*event
, wxWindow
*win
)
808 if (!win
->HasVMT()) return;
810 if (win
->GetDropTarget())
814 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
815 win
->GetDropTarget()->Drop( event
, x
, y
);
819 g_free (event->dropdataavailable.data);
820 g_free (event->dropdataavailable.data_type);
824 //-----------------------------------------------------------------------------
826 //-----------------------------------------------------------------------------
828 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
830 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
831 EVT_SIZE(wxWindow::OnSize
)
832 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
833 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
834 EVT_IDLE(wxWindow::OnIdle
)
839 m_widget
= (GtkWidget
*) NULL
;
840 m_wxwindow
= (GtkWidget
*) NULL
;
841 m_parent
= (wxWindow
*) NULL
;
842 m_children
.DeleteContents( FALSE
);
852 m_eventHandler
= this;
853 m_windowValidator
= (wxValidator
*) NULL
;
855 m_cursor
= (wxCursor
*) NULL
;
856 m_font
= *wxSWISS_FONT
;
858 m_windowName
= "noname";
859 m_constraints
= (wxLayoutConstraints
*) NULL
;
860 m_constraintsInvolvedIn
= (wxList
*) NULL
;
861 m_windowSizer
= (wxSizer
*) NULL
;
862 m_sizerParent
= (wxWindow
*) NULL
;
863 m_autoLayout
= FALSE
;
867 m_hasScrolling
= FALSE
;
868 m_hAdjust
= (GtkAdjustment
*) NULL
;
869 m_vAdjust
= (GtkAdjustment
*) NULL
;
870 m_oldHorizontalPos
= 0.0;
871 m_oldVerticalPos
= 0.0;
874 m_pDropTarget
= (wxDropTarget
*) NULL
;
876 m_hasOwnStyle
= FALSE
;
879 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
880 const wxPoint
&pos
, const wxSize
&size
,
881 long style
, const wxString
&name
)
887 m_cursor
= (wxCursor
*) NULL
;
889 PreCreation( parent
, id
, pos
, size
, style
, name
);
891 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
892 m_hasScrolling
= TRUE
;
894 GtkScrolledWindow
*s_window
;
895 s_window
= GTK_SCROLLED_WINDOW(m_widget
);
897 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
898 scroll_class
->scrollbar_spacing
= 0;
900 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
902 m_oldHorizontalPos
= 0.0;
903 m_oldVerticalPos
= 0.0;
905 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
906 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
908 gtk_signal_connect (GTK_OBJECT (m_hAdjust
), "value_changed",
909 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
910 gtk_signal_connect (GTK_OBJECT (m_vAdjust
), "value_changed",
911 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
913 gtk_signal_connect (GTK_OBJECT (m_hAdjust
), "changed",
914 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
915 gtk_signal_connect (GTK_OBJECT (m_vAdjust
), "changed",
916 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
918 GtkViewport
*viewport
;
919 viewport
= GTK_VIEWPORT(s_window
->viewport
);
921 if (m_windowStyle
& wxRAISED_BORDER
)
923 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
925 else if (m_windowStyle
& wxSUNKEN_BORDER
)
927 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
931 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
934 m_wxwindow
= gtk_myfixed_new();
936 if (m_wxwindow
) GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
938 if (m_windowStyle
& wxTAB_TRAVERSAL
== wxTAB_TRAVERSAL
)
939 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
941 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
943 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
945 // shut the viewport up
946 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
947 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
949 // I _really_ don't want scrollbars in the beginning
950 m_vAdjust
->lower
= 0.0;
951 m_vAdjust
->upper
= 1.0;
952 m_vAdjust
->value
= 0.0;
953 m_vAdjust
->step_increment
= 1.0;
954 m_vAdjust
->page_increment
= 1.0;
955 m_vAdjust
->page_size
= 5.0;
956 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
957 m_hAdjust
->lower
= 0.0;
958 m_hAdjust
->upper
= 1.0;
959 m_hAdjust
->value
= 0.0;
960 m_hAdjust
->step_increment
= 1.0;
961 m_hAdjust
->page_increment
= 1.0;
962 m_hAdjust
->page_size
= 5.0;
963 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
965 gtk_widget_show( m_wxwindow
);
974 wxWindow::~wxWindow(void)
978 if (m_pDropTarget
) delete m_pDropTarget
;
980 if (m_parent
) m_parent
->RemoveChild( this );
981 if (m_widget
) Show( FALSE
);
985 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
987 if (m_widget
) gtk_widget_destroy( m_widget
);
991 DeleteRelatedConstraints();
994 // This removes any dangling pointers to this window
995 // in other windows' constraintsInvolvedIn lists.
996 UnsetConstraints(m_constraints
);
997 delete m_constraints
;
998 m_constraints
= (wxLayoutConstraints
*) NULL
;
1002 delete m_windowSizer
;
1003 m_windowSizer
= (wxSizer
*) NULL
;
1005 // If this is a child of a sizer, remove self from parent
1006 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
1008 // Just in case the window has been Closed, but
1009 // we're then deleting immediately: don't leave
1010 // dangling pointers.
1011 wxPendingDelete
.DeleteObject(this);
1013 // Just in case we've loaded a top-level window via
1014 // wxWindow::LoadNativeDialog but we weren't a dialog
1016 wxTopLevelWindows
.DeleteObject(this);
1018 if (m_windowValidator
) delete m_windowValidator
;
1021 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1022 const wxPoint
&pos
, const wxSize
&size
,
1023 long style
, const wxString
&name
)
1025 if (m_needParent
&& (parent
== NULL
))
1026 wxFatalError( "Need complete parent.", name
);
1028 m_widget
= (GtkWidget
*) NULL
;
1031 m_children
.DeleteContents( FALSE
);
1035 if (m_width
== -1) m_width
= 20;
1037 if (m_height
== -1) m_height
= 20;
1043 m_eventHandler
= this;
1046 if (m_cursor
== NULL
)
1047 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1048 m_font
= *wxSWISS_FONT
;
1049 m_backgroundColour
= wxWHITE
;
1050 m_foregroundColour
= wxBLACK
;
1051 m_windowStyle
= style
;
1052 m_windowName
= name
;
1053 m_constraints
= (wxLayoutConstraints
*) NULL
;
1054 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1055 m_windowSizer
= (wxSizer
*) NULL
;
1056 m_sizerParent
= (wxWindow
*) NULL
;
1057 m_autoLayout
= FALSE
;
1058 m_pDropTarget
= (wxDropTarget
*) NULL
;
1060 m_windowValidator
= (wxValidator
*) NULL
;
1061 m_hasOwnStyle
= FALSE
;
1064 void wxWindow::PostCreation(void)
1066 if (m_parent
) m_parent
->AddChild( this );
1070 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1071 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1073 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1074 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1077 ConnectWidget( GetConnectWidget() );
1079 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1083 gtk_widget_realize( m_wxwindow
);
1084 gdk_gc_set_exposures( m_wxwindow
->style
->fg_gc
[0], TRUE
);
1087 SetCursor( *wxSTANDARD_CURSOR
);
1092 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1094 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1095 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1097 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1098 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1100 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1101 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1103 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1104 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1106 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1107 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1109 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1110 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1112 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1113 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1115 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1116 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1119 bool wxWindow::HasVMT(void)
1124 bool wxWindow::Close( bool force
)
1126 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1128 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1129 event
.SetEventObject(this);
1130 event
.SetForce(force
);
1132 return GetEventHandler()->ProcessEvent(event
);
1135 bool wxWindow::Destroy(void)
1137 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1144 bool wxWindow::DestroyChildren(void)
1149 while ((node
= GetChildren()->First()) != (wxNode
*)NULL
)
1152 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1155 if (GetChildren()->Member(child
)) delete node
;
1162 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1164 // are we to set fonts here ?
1167 void wxWindow::ImplementSetSize(void)
1169 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1170 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1171 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_minWidth
;
1172 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_minHeight
;
1173 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1176 void wxWindow::ImplementSetPosition(void)
1178 if (IS_KIND_OF(this,wxFrame
) || IS_KIND_OF(this,wxDialog
))
1180 if ((m_x
!= -1) || (m_y
!= -1))
1181 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
1187 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1191 if ((m_parent
) && (m_parent
->m_wxwindow
))
1192 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
, m_y
);
1194 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1197 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1199 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1201 if (m_resizing
) return; // I don't like recursions
1209 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1211 if (newX
== -1) newX
= m_x
;
1212 if (newY
== -1) newY
= m_y
;
1213 if (newW
== -1) newW
= m_width
;
1214 if (newH
== -1) newH
= m_height
;
1217 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1219 if (newW
== -1) newW
= 80;
1222 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1224 if (newH
== -1) newH
= 26;
1227 if ((m_x
!= newX
) || (m_y
!= newY
) || (!m_sizeSet
))
1231 ImplementSetPosition();
1233 if ((m_width
!= newW
) || (m_height
!= newH
) || (!m_sizeSet
))
1241 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1242 event
.SetEventObject( this );
1243 ProcessEvent( event
);
1248 void wxWindow::SetSize( int width
, int height
)
1250 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1253 void wxWindow::Move( int x
, int y
)
1255 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1258 void wxWindow::GetSize( int *width
, int *height
) const
1260 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1262 if (width
) (*width
) = m_width
;
1263 if (height
) (*height
) = m_height
;
1266 void wxWindow::SetClientSize( int width
, int height
)
1268 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1272 SetSize( width
, height
);
1279 if (!m_hasScrolling
)
1282 do we have sunken dialogs ?
1284 GtkStyleClass *window_class = m_wxwindow->style->klass;
1286 dw += 2 * window_class->xthickness;
1287 dh += 2 * window_class->ythickness;
1292 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1293 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1295 GtkWidget
*viewport
= scroll_window
->viewport
;
1296 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1298 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1299 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1301 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1302 (m_windowStyle
& wxSUNKEN_BORDER
))
1304 dw
+= 2 * viewport_class
->xthickness
;
1305 dh
+= 2 * viewport_class
->ythickness
;
1308 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1310 dw
+= vscrollbar
->allocation
.width
;
1311 dw
+= scroll_class
->scrollbar_spacing
;
1314 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1316 dh
+= hscrollbar
->allocation
.height
;
1317 dw
+= scroll_class
->scrollbar_spacing
;
1321 SetSize( width
+dw
, height
+dh
);
1325 void wxWindow::GetClientSize( int *width
, int *height
) const
1327 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1331 if (width
) (*width
) = m_width
;
1332 if (height
) (*height
) = m_height
;
1339 if (!m_hasScrolling
)
1342 do we have sunken dialogs ?
1344 GtkStyleClass *window_class = m_wxwindow->style->klass;
1346 dw += 2 * window_class->xthickness;
1347 dh += 2 * window_class->ythickness;
1352 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1353 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1355 GtkWidget
*viewport
= scroll_window
->viewport
;
1356 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1358 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1359 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1361 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1362 (m_windowStyle
& wxSUNKEN_BORDER
))
1364 dw
+= 2 * viewport_class
->xthickness
;
1365 dh
+= 2 * viewport_class
->ythickness
;
1368 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1370 // dw += vscrollbar->allocation.width;
1371 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1372 dw
+= scroll_class
->scrollbar_spacing
;
1375 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1377 // dh += hscrollbar->allocation.height;
1379 dh
+= scroll_class
->scrollbar_spacing
;
1383 if (width
) (*width
) = m_width
- dw
;
1384 if (height
) (*height
) = m_height
- dh
;
1388 void wxWindow::GetPosition( int *x
, int *y
) const
1390 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1396 void wxWindow::ClientToScreen( int *x
, int *y
)
1398 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1400 GdkWindow
*source
= (GdkWindow
*) NULL
;
1402 source
= m_wxwindow
->window
;
1404 source
= m_widget
->window
;
1408 gdk_window_get_origin( source
, &org_x
, &org_y
);
1412 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1414 org_x
+= m_widget
->allocation
.x
;
1415 org_y
+= m_widget
->allocation
.y
;
1423 void wxWindow::ScreenToClient( int *x
, int *y
)
1425 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1427 GdkWindow
*source
= (GdkWindow
*) NULL
;
1429 source
= m_wxwindow
->window
;
1431 source
= m_widget
->window
;
1435 gdk_window_get_origin( source
, &org_x
, &org_y
);
1439 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1441 org_x
+= m_widget
->allocation
.x
;
1442 org_y
+= m_widget
->allocation
.y
;
1450 void wxWindow::Centre( int direction
)
1452 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1454 if (IS_KIND_OF(this,wxDialog
) || IS_KIND_OF(this,wxFrame
))
1456 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (gdk_screen_width () - m_width
) / 2;
1457 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (gdk_screen_height () - m_height
) / 2;
1458 ImplementSetPosition();
1466 m_parent
->GetSize( &p_w
, &p_h
);
1467 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (p_w
- m_width
) / 2;
1468 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (p_h
- m_height
) / 2;
1469 ImplementSetPosition();
1474 void wxWindow::Fit(void)
1476 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1480 wxNode
*node
= GetChildren()->First();
1483 wxWindow
*win
= (wxWindow
*)node
->Data();
1485 win
->GetPosition(&wx
, &wy
);
1486 win
->GetSize(&ww
, &wh
);
1487 if ( wx
+ ww
> maxX
)
1489 if ( wy
+ wh
> maxY
)
1492 node
= node
->Next();
1494 SetClientSize(maxX
+ 5, maxY
+ 10);
1497 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1499 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1507 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1509 //if (GetAutoLayout()) Layout();
1512 bool wxWindow::Show( bool show
)
1514 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1517 gtk_widget_show( m_widget
);
1519 gtk_widget_hide( m_widget
);
1524 void wxWindow::Enable( bool enable
)
1526 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1528 m_isEnabled
= enable
;
1529 gtk_widget_set_sensitive( m_widget
, enable
);
1530 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1533 int wxWindow::GetCharHeight(void) const
1535 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1539 wxFAIL_MSG( "invalid font" );
1543 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1544 return font
->ascent
+ font
->descent
;
1547 int wxWindow::GetCharWidth(void) const
1549 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1553 wxFAIL_MSG( "invalid font" );
1557 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1558 return gdk_string_width( font
, "H" );
1561 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1562 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1564 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1566 wxFont fontToUse
= m_font
;
1567 if (theFont
) fontToUse
= *theFont
;
1569 if (!fontToUse
.Ok())
1571 wxFAIL_MSG( "invalid font" );
1574 wxASSERT_MSG( (m_font
.Ok()), "invalid font" );
1576 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1577 if (x
) (*x
) = gdk_string_width( font
, string
);
1578 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1579 if (descent
) (*descent
) = font
->descent
;
1580 if (externalLeading
) (*externalLeading
) = 0; // ??
1583 void wxWindow::MakeModal( bool modal
)
1586 // Disable all other windows
1587 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1589 wxNode
*node
= wxTopLevelWindows
.First();
1592 wxWindow
*win
= (wxWindow
*)node
->Data();
1594 win
->Enable(!modal
);
1596 node
= node
->Next();
1601 void wxWindow::SetFocus(void)
1603 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1605 GtkWidget
*connect_widget
= GetConnectWidget();
1608 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) && !GTK_WIDGET_HAS_FOCUS (connect_widget
) )
1610 gtk_widget_grab_focus (connect_widget
);
1615 bool wxWindow::OnClose(void)
1620 void wxWindow::AddChild( wxWindow
*child
)
1622 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1623 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window need client area" );
1624 wxASSERT_MSG( (child
!= NULL
), "invalid child" );
1625 wxASSERT_MSG( (child
->m_widget
!= NULL
), "invalid child" );
1627 // Addchild is (often) called before the program
1628 // has left the parents constructor so that no
1629 // virtual tables work yet. The approach below
1630 // practically imitates virtual tables, i.e. it
1631 // implements a different AddChild() behaviour
1632 // for wxFrame, wxDialog, wxWindow and
1633 // wxMDIParentFrame.
1635 // wxFrame and wxDialog as children aren't placed into the parents
1637 if (( IS_KIND_OF(child
,wxFrame
) || IS_KIND_OF(child
,wxDialog
) ) &&
1638 (!IS_KIND_OF(child
,wxMDIChildFrame
)))
1640 m_children
.Append( child
);
1642 if ((child
->m_x
!= -1) && (child
->m_y
!= -1))
1643 gtk_widget_set_uposition( child
->m_widget
, child
->m_x
, child
->m_y
);
1648 // In the case of an wxMDIChildFrame descendant, we use the
1649 // client windows's AddChild()
1651 if (IS_KIND_OF(this,wxMDIParentFrame
))
1653 if (IS_KIND_OF(child
,wxMDIChildFrame
))
1655 wxMDIClientWindow
*client
= ((wxMDIParentFrame
*)this)->GetClientWindow();
1658 client
->AddChild( child
);
1664 // wxNotebook is very special, so it has a private AddChild()
1666 if (IS_KIND_OF(this,wxNotebook
))
1668 wxNotebook
*tab
= (wxNotebook
*)this;
1669 tab
->AddChild( child
);
1673 // wxFrame has a private AddChild
1675 if (IS_KIND_OF(this,wxFrame
) && !IS_KIND_OF(this,wxMDIChildFrame
))
1677 wxFrame
*frame
= (wxFrame
*)this;
1678 frame
->AddChild( child
);
1684 m_children
.Append( child
);
1685 if (m_wxwindow
) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), child
->m_widget
,
1686 child
->m_x
, child
->m_y
);
1688 gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height
);
1691 wxList
*wxWindow::GetChildren(void)
1693 return (&m_children
);
1696 void wxWindow::RemoveChild( wxWindow
*child
)
1699 GetChildren()->DeleteObject( child
);
1700 child
->m_parent
= (wxWindow
*) NULL
;
1703 void wxWindow::SetReturnCode( int retCode
)
1705 m_retCode
= retCode
;
1708 int wxWindow::GetReturnCode(void)
1713 void wxWindow::Raise(void)
1715 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1717 if (m_widget
) gdk_window_raise( m_widget
->window
);
1720 void wxWindow::Lower(void)
1722 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1724 if (m_widget
) gdk_window_lower( m_widget
->window
);
1727 wxEvtHandler
*wxWindow::GetEventHandler(void)
1729 return m_eventHandler
;
1732 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
1734 m_eventHandler
= handler
;
1737 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
1739 handler
->SetNextHandler(GetEventHandler());
1740 SetEventHandler(handler
);
1743 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
1745 if (GetEventHandler())
1747 wxEvtHandler
*handlerA
= GetEventHandler();
1748 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
1749 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
1750 SetEventHandler(handlerB
);
1754 return (wxEvtHandler
*) NULL
;
1760 return (wxEvtHandler
*) NULL
;
1763 wxValidator
*wxWindow::GetValidator(void)
1765 return m_windowValidator
;
1768 void wxWindow::SetValidator( const wxValidator
& validator
)
1770 if (m_windowValidator
) delete m_windowValidator
;
1771 m_windowValidator
= validator
.Clone();
1772 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
1775 bool wxWindow::IsBeingDeleted(void)
1780 void wxWindow::SetId( wxWindowID id
)
1785 wxWindowID
wxWindow::GetId(void)
1790 void wxWindow::SetCursor( const wxCursor
&cursor
)
1792 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1794 if (m_cursor
== NULL
)
1796 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1797 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1802 if (*((wxCursor
*)&cursor
) == m_cursor
) return;
1807 *m_cursor
= *wxSTANDARD_CURSOR
;
1810 if ((m_widget
) && (m_widget
->window
))
1811 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
1813 if ((m_wxwindow
) && (m_wxwindow
->window
))
1814 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
1817 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
1819 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1821 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
1824 gdk_window_clear_area( m_wxwindow
->window
,
1838 GetClientSize( &w
, &h
);
1840 GdkRectangle gdk_rect
;
1844 gdk_rect
.height
= h
;
1845 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1850 GdkRectangle gdk_rect
;
1851 gdk_rect
.x
= rect
->x
;
1852 gdk_rect
.y
= rect
->y
;
1853 gdk_rect
.width
= rect
->width
;
1854 gdk_rect
.height
= rect
->height
;
1857 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1859 gtk_widget_draw( m_widget
, &gdk_rect
);
1863 wxRegion
wxWindow::GetUpdateRegion() const
1865 return m_updateRegion
;
1868 bool wxWindow::IsExposed( int x
, int y
) const
1870 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
1873 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
1875 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
1878 bool wxWindow::IsExposed( const wxPoint
& pt
) const
1880 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
1883 bool wxWindow::IsExposed( const wxRect
& rect
) const
1885 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
1888 void wxWindow::Clear(void)
1890 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1892 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
1895 wxColour
wxWindow::GetBackgroundColour(void) const
1897 return m_backgroundColour
;
1900 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
1902 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1904 m_backgroundColour
= colour
;
1907 m_backgroundColour
.CalcPixel( m_wxwindow
->style
->colormap
);
1908 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
1909 gdk_window_clear( m_wxwindow
->window
);
1914 wxColour
wxWindow::GetForegroundColour(void) const
1916 return m_foregroundColour
;
1919 void wxWindow::SetForegroundColour( const wxColour
&colour
)
1921 m_foregroundColour
= colour
;
1924 bool wxWindow::Validate(void)
1926 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1928 wxNode
*node
= GetChildren()->First();
1931 wxWindow
*child
= (wxWindow
*)node
->Data();
1932 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
1934 node
= node
->Next();
1939 bool wxWindow::TransferDataToWindow(void)
1941 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1943 wxNode
*node
= GetChildren()->First();
1946 wxWindow
*child
= (wxWindow
*)node
->Data();
1947 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
1948 !child
->GetValidator()->TransferToWindow() )
1950 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
1953 node
= node
->Next();
1958 bool wxWindow::TransferDataFromWindow(void)
1960 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1962 wxNode
*node
= GetChildren()->First();
1965 wxWindow
*child
= (wxWindow
*)node
->Data();
1966 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
1968 node
= node
->Next();
1973 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
1975 m_acceleratorTable
= accel
;
1978 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
1980 TransferDataToWindow();
1983 void wxWindow::InitDialog(void)
1985 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1987 wxInitDialogEvent
event(GetId());
1988 event
.SetEventObject( this );
1989 GetEventHandler()->ProcessEvent(event
);
1992 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
1994 menu
->SetInvokingWindow( win
);
1995 wxNode
*node
= menu
->m_items
.First();
1998 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
1999 if (menuitem
->IsSubMenu())
2000 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2001 node
= node
->Next();
2005 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
2007 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2009 SetInvokingWindow( menu
, this );
2010 gtk_menu_popup( GTK_MENU(menu
->m_menu
), (GtkWidget
*) NULL
, (GtkWidget
*) NULL
, (GtkMenuPositionFunc
) NULL
, NULL
, 0, 0 );
2014 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2016 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2018 GtkWidget
*dnd_widget
= GetConnectWidget();
2020 DisconnectDnDWidget( dnd_widget
);
2022 if (m_pDropTarget
) delete m_pDropTarget
;
2023 m_pDropTarget
= dropTarget
;
2025 ConnectDnDWidget( dnd_widget
);
2028 wxDropTarget
*wxWindow::GetDropTarget() const
2030 return m_pDropTarget
;
2033 void wxWindow::ConnectDnDWidget( GtkWidget
*widget
)
2035 if (!m_pDropTarget
) return;
2037 m_pDropTarget
->RegisterWidget( widget
);
2039 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
2040 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2043 void wxWindow::DisconnectDnDWidget( GtkWidget
*widget
)
2045 if (!m_pDropTarget
) return;
2047 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
2048 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2050 m_pDropTarget
->UnregisterWidget( widget
);
2053 GtkWidget
* wxWindow::GetConnectWidget(void)
2055 GtkWidget
*connect_widget
= m_widget
;
2056 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2058 return connect_widget
;
2061 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2063 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2064 return (window
== m_widget
->window
);
2067 void wxWindow::SetFont( const wxFont
&font
)
2069 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2071 if (((wxFont
*)&font
)->Ok())
2074 m_font
= *wxSWISS_FONT
;
2076 GtkStyle
*style
= (GtkStyle
*) NULL
;
2079 m_hasOwnStyle
= TRUE
;
2080 style
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2084 style
= gtk_widget_get_style( m_widget
);
2087 gdk_font_unref( style
->font
);
2088 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2090 gtk_widget_set_style( m_widget
, style
);
2093 wxFont
*wxWindow::GetFont(void)
2098 void wxWindow::SetWindowStyleFlag( long flag
)
2100 m_windowStyle
= flag
;
2103 long wxWindow::GetWindowStyleFlag(void) const
2105 return m_windowStyle
;
2108 void wxWindow::CaptureMouse(void)
2110 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2112 wxASSERT_MSG( (g_capturing
== FALSE
), "CaptureMouse called twice" );
2114 GtkWidget
*connect_widget
= GetConnectWidget();
2115 gtk_grab_add( connect_widget
);
2116 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
2118 (GDK_BUTTON_PRESS_MASK
|
2119 GDK_BUTTON_RELEASE_MASK
|
2120 GDK_POINTER_MOTION_MASK
),
2121 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
2125 void wxWindow::ReleaseMouse(void)
2127 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2129 wxASSERT_MSG( (g_capturing
== TRUE
), "ReleaseMouse called twice" );
2131 GtkWidget
*connect_widget
= GetConnectWidget();
2132 gtk_grab_remove( connect_widget
);
2133 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2134 g_capturing
= FALSE
;
2137 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2141 wxString
wxWindow::GetTitle(void) const
2143 return (wxString
&)m_windowName
;
2146 wxString
wxWindow::GetLabel(void) const
2151 void wxWindow::SetName( const wxString
&name
)
2153 m_windowName
= name
;
2156 wxString
wxWindow::GetName(void) const
2158 return (wxString
&)m_windowName
;
2161 bool wxWindow::IsShown(void) const
2166 bool wxWindow::IsRetained(void)
2171 wxWindow
*wxWindow::FindWindow( long id
)
2173 if (id
== m_windowId
) return this;
2174 wxNode
*node
= m_children
.First();
2177 wxWindow
*child
= (wxWindow
*)node
->Data();
2178 wxWindow
*res
= child
->FindWindow( id
);
2179 if (res
) return res
;
2180 node
= node
->Next();
2182 return (wxWindow
*) NULL
;
2185 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2187 if (name
== m_windowName
) return this;
2188 wxNode
*node
= m_children
.First();
2191 wxWindow
*child
= (wxWindow
*)node
->Data();
2192 wxWindow
*res
= child
->FindWindow( name
);
2193 if (res
) return res
;
2194 node
= node
->Next();
2196 return (wxWindow
*) NULL
;
2199 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2200 int range
, bool WXUNUSED(refresh
) )
2202 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2204 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2206 if (!m_wxwindow
) return;
2208 if (orient
== wxHORIZONTAL
)
2210 float fpos
= (float)pos
;
2211 m_oldHorizontalPos
= fpos
;
2212 float frange
= (float)range
;
2213 float fthumb
= (float)thumbVisible
;
2215 if ((fabs(fpos
-m_hAdjust
->value
) < 0.2) &&
2216 (fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2217 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2220 m_hAdjust
->lower
= 0.0;
2221 m_hAdjust
->upper
= frange
;
2222 m_hAdjust
->value
= fpos
;
2223 m_hAdjust
->step_increment
= 1.0;
2224 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2225 m_hAdjust
->page_size
= fthumb
;
2229 float fpos
= (float)pos
;
2230 m_oldVerticalPos
= fpos
;
2231 float frange
= (float)range
;
2232 float fthumb
= (float)thumbVisible
;
2234 if ((fabs(fpos
-m_vAdjust
->value
) < 0.2) &&
2235 (fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2236 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2239 m_vAdjust
->lower
= 0.0;
2240 m_vAdjust
->upper
= frange
;
2241 m_vAdjust
->value
= fpos
;
2242 m_vAdjust
->step_increment
= 1.0;
2243 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2244 m_vAdjust
->page_size
= fthumb
;
2247 if (m_wxwindow
->window
)
2249 if (orient
== wxHORIZONTAL
)
2250 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2252 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2254 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2258 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2260 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2262 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2264 if (!m_wxwindow
) return;
2266 if (orient
== wxHORIZONTAL
)
2268 float fpos
= (float)pos
;
2269 m_oldHorizontalPos
= fpos
;
2271 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2272 m_hAdjust
->value
= fpos
;
2276 float fpos
= (float)pos
;
2277 m_oldVerticalPos
= fpos
;
2278 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2279 m_vAdjust
->value
= fpos
;
2282 if (m_wxwindow
->window
)
2284 if (orient
== wxHORIZONTAL
)
2285 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2287 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2291 int wxWindow::GetScrollThumb( int orient
) const
2293 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2295 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2297 if (!m_wxwindow
) return 0;
2299 if (orient
== wxHORIZONTAL
)
2300 return (int)(m_hAdjust
->page_size
+0.5);
2302 return (int)(m_vAdjust
->page_size
+0.5);
2305 int wxWindow::GetScrollPos( int orient
) const
2307 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2309 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2311 if (!m_wxwindow
) return 0;
2313 if (orient
== wxHORIZONTAL
)
2314 return (int)(m_hAdjust
->value
+0.5);
2316 return (int)(m_vAdjust
->value
+0.5);
2319 int wxWindow::GetScrollRange( int orient
) const
2321 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2323 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2325 if (!m_wxwindow
) return 0;
2327 if (orient
== wxHORIZONTAL
)
2328 return (int)(m_hAdjust
->upper
+0.5);
2330 return (int)(m_vAdjust
->upper
+0.5);
2333 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2335 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2337 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2339 if (!m_wxwindow
) return;
2343 GetClientSize( &cw
, &ch
);
2345 int w
= cw
- abs(dx
);
2346 int h
= ch
- abs(dy
);
2347 if ((h
< 0) || (w
< 0))
2354 if (dx
< 0) s_x
= -dx
;
2355 if (dy
< 0) s_y
= -dy
;
2358 if (dx
> 0) d_x
= dx
;
2359 if (dy
> 0) d_y
= dy
;
2360 gdk_window_copy_area( m_wxwindow
->window
, m_wxwindow
->style
->fg_gc
[0], d_x
, d_y
,
2361 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2364 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2365 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2366 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2367 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2369 Refresh( TRUE
, &rect
);
2372 //-------------------------------------------------------------------------------------
2374 //-------------------------------------------------------------------------------------
2376 wxLayoutConstraints
*wxWindow::GetConstraints(void) const
2378 return m_constraints
;
2381 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2385 UnsetConstraints(m_constraints
);
2386 delete m_constraints
;
2388 m_constraints
= constraints
;
2391 // Make sure other windows know they're part of a 'meaningful relationship'
2392 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2393 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2394 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2395 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2396 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2397 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2398 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2399 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2400 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2401 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2402 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2403 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2404 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2405 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2406 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2407 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2413 void wxWindow::SetAutoLayout( bool autoLayout
)
2415 m_autoLayout
= autoLayout
;
2418 bool wxWindow::GetAutoLayout(void) const
2420 return m_autoLayout
;
2423 wxSizer
*wxWindow::GetSizer(void) const
2425 return m_windowSizer
;
2428 void wxWindow::SetSizerParent( wxWindow
*win
)
2430 m_sizerParent
= win
;
2433 wxWindow
*wxWindow::GetSizerParent(void) const
2435 return m_sizerParent
;
2438 // This removes any dangling pointers to this window
2439 // in other windows' constraintsInvolvedIn lists.
2440 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2444 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2445 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2446 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2447 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2448 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2449 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2450 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2451 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2452 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2453 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2454 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2455 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2456 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2457 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2458 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2459 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2463 // Back-pointer to other windows we're involved with, so if we delete
2464 // this window, we must delete any constraints we're involved with.
2465 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2467 if (!m_constraintsInvolvedIn
)
2468 m_constraintsInvolvedIn
= new wxList
;
2469 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2470 m_constraintsInvolvedIn
->Append(otherWin
);
2473 // REMOVE back-pointer to other windows we're involved with.
2474 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2476 if (m_constraintsInvolvedIn
)
2477 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2480 // Reset any constraints that mention this window
2481 void wxWindow::DeleteRelatedConstraints(void)
2483 if (m_constraintsInvolvedIn
)
2485 wxNode
*node
= m_constraintsInvolvedIn
->First();
2488 wxWindow
*win
= (wxWindow
*)node
->Data();
2489 wxNode
*next
= node
->Next();
2490 wxLayoutConstraints
*constr
= win
->GetConstraints();
2492 // Reset any constraints involving this window
2495 constr
->left
.ResetIfWin((wxWindow
*)this);
2496 constr
->top
.ResetIfWin((wxWindow
*)this);
2497 constr
->right
.ResetIfWin((wxWindow
*)this);
2498 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2499 constr
->width
.ResetIfWin((wxWindow
*)this);
2500 constr
->height
.ResetIfWin((wxWindow
*)this);
2501 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2502 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2507 delete m_constraintsInvolvedIn
;
2508 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2512 void wxWindow::SetSizer(wxSizer
*sizer
)
2514 m_windowSizer
= sizer
;
2516 sizer
->SetSizerParent((wxWindow
*)this);
2523 bool wxWindow::Layout(void)
2525 if (GetConstraints())
2528 GetClientSize(&w
, &h
);
2529 GetConstraints()->width
.SetValue(w
);
2530 GetConstraints()->height
.SetValue(h
);
2533 // If top level (one sizer), evaluate the sizer's constraints.
2537 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2538 GetSizer()->LayoutPhase1(&noChanges
);
2539 GetSizer()->LayoutPhase2(&noChanges
);
2540 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2545 // Otherwise, evaluate child constraints
2546 ResetConstraints(); // Mark all constraints as unevaluated
2547 DoPhase(1); // Just one phase need if no sizers involved
2549 SetConstraintSizes(); // Recursively set the real window sizes
2555 // Do a phase of evaluating constraints:
2556 // the default behaviour. wxSizers may do a similar
2557 // thing, but also impose their own 'constraints'
2558 // and order the evaluation differently.
2559 bool wxWindow::LayoutPhase1(int *noChanges
)
2561 wxLayoutConstraints
*constr
= GetConstraints();
2564 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2570 bool wxWindow::LayoutPhase2(int *noChanges
)
2580 // Do a phase of evaluating child constraints
2581 bool wxWindow::DoPhase(int phase
)
2583 int noIterations
= 0;
2584 int maxIterations
= 500;
2588 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2592 wxNode
*node
= GetChildren()->First();
2595 wxWindow
*child
= (wxWindow
*)node
->Data();
2596 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2598 wxLayoutConstraints
*constr
= child
->GetConstraints();
2601 if (succeeded
.Member(child
))
2606 int tempNoChanges
= 0;
2607 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2608 noChanges
+= tempNoChanges
;
2611 succeeded
.Append(child
);
2616 node
= node
->Next();
2623 void wxWindow::ResetConstraints(void)
2625 wxLayoutConstraints
*constr
= GetConstraints();
2628 constr
->left
.SetDone(FALSE
);
2629 constr
->top
.SetDone(FALSE
);
2630 constr
->right
.SetDone(FALSE
);
2631 constr
->bottom
.SetDone(FALSE
);
2632 constr
->width
.SetDone(FALSE
);
2633 constr
->height
.SetDone(FALSE
);
2634 constr
->centreX
.SetDone(FALSE
);
2635 constr
->centreY
.SetDone(FALSE
);
2637 wxNode
*node
= GetChildren()->First();
2640 wxWindow
*win
= (wxWindow
*)node
->Data();
2641 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2642 win
->ResetConstraints();
2643 node
= node
->Next();
2647 // Need to distinguish between setting the 'fake' size for
2648 // windows and sizers, and setting the real values.
2649 void wxWindow::SetConstraintSizes(bool recurse
)
2651 wxLayoutConstraints
*constr
= GetConstraints();
2652 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2653 constr
->width
.GetDone() && constr
->height
.GetDone())
2655 int x
= constr
->left
.GetValue();
2656 int y
= constr
->top
.GetValue();
2657 int w
= constr
->width
.GetValue();
2658 int h
= constr
->height
.GetValue();
2660 // If we don't want to resize this window, just move it...
2661 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2662 (constr
->height
.GetRelationship() != wxAsIs
))
2664 // Calls Layout() recursively. AAAGH. How can we stop that.
2665 // Simply take Layout() out of non-top level OnSizes.
2666 SizerSetSize(x
, y
, w
, h
);
2675 char *windowClass
= this->GetClassInfo()->GetClassName();
2678 if (GetName() == "")
2679 winName
= _("unnamed");
2681 winName
= GetName();
2682 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2683 if (!constr
->left
.GetDone())
2684 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2685 if (!constr
->right
.GetDone())
2686 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2687 if (!constr
->width
.GetDone())
2688 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2689 if (!constr
->height
.GetDone())
2690 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2691 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2696 wxNode
*node
= GetChildren()->First();
2699 wxWindow
*win
= (wxWindow
*)node
->Data();
2700 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2701 win
->SetConstraintSizes();
2702 node
= node
->Next();
2707 // This assumes that all sizers are 'on' the same
2708 // window, i.e. the parent of this window.
2709 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2711 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2712 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2716 m_sizerParent
->GetPosition(&xp
, &yp
);
2717 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2722 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2726 TransformSizerToActual(&xx
, &yy
);
2727 SetSize(xx
, yy
, w
, h
);
2730 void wxWindow::SizerMove(int x
, int y
)
2734 TransformSizerToActual(&xx
, &yy
);
2738 // Only set the size/position of the constraint (if any)
2739 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2741 wxLayoutConstraints
*constr
= GetConstraints();
2746 constr
->left
.SetValue(x
);
2747 constr
->left
.SetDone(TRUE
);
2751 constr
->top
.SetValue(y
);
2752 constr
->top
.SetDone(TRUE
);
2756 constr
->width
.SetValue(w
);
2757 constr
->width
.SetDone(TRUE
);
2761 constr
->height
.SetValue(h
);
2762 constr
->height
.SetDone(TRUE
);
2767 void wxWindow::MoveConstraint(int x
, int y
)
2769 wxLayoutConstraints
*constr
= GetConstraints();
2774 constr
->left
.SetValue(x
);
2775 constr
->left
.SetDone(TRUE
);
2779 constr
->top
.SetValue(y
);
2780 constr
->top
.SetDone(TRUE
);
2785 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2787 wxLayoutConstraints
*constr
= GetConstraints();
2790 *w
= constr
->width
.GetValue();
2791 *h
= constr
->height
.GetValue();
2797 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2799 wxLayoutConstraints
*constr
= GetConstraints();
2802 *w
= constr
->width
.GetValue();
2803 *h
= constr
->height
.GetValue();
2806 GetClientSize(w
, h
);
2809 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2811 wxLayoutConstraints
*constr
= GetConstraints();
2814 *x
= constr
->left
.GetValue();
2815 *y
= constr
->top
.GetValue();
2821 bool wxWindow::AcceptsFocus() const
2823 return IsEnabled() && IsShown();
2826 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )