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 wxWindow
*g_captureWindow
= (wxWindow
*)NULL
;
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;
137 wxPaintEvent
event( win
->GetId() );
138 event
.SetEventObject( win
);
139 win
->GetEventHandler()->ProcessEvent( event
);
141 win
->m_updateRegion
.Clear();
144 //-----------------------------------------------------------------------------
145 // "draw" (of m_wxwindow, not of m_widget)
146 //-----------------------------------------------------------------------------
148 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
150 if (!win
->HasVMT()) return;
151 if (g_blockEventsOnDrag
) return;
153 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
155 wxPaintEvent
event( win
->GetId() );
156 event
.SetEventObject( win
);
157 win
->GetEventHandler()->ProcessEvent( event
);
159 win
->m_updateRegion
.Clear();
162 //-----------------------------------------------------------------------------
164 //-----------------------------------------------------------------------------
166 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
168 if (!win
->HasVMT()) return FALSE
;
169 if (g_blockEventsOnDrag
) return FALSE
;
172 printf( "OnKeyPress from " );
173 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
174 printf( win->GetClassInfo()->GetClassName() );
179 switch (gdk_event
->keyval
)
181 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
182 case GDK_Tab
: key_code
= WXK_TAB
; break;
183 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
184 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
185 case GDK_Return
: key_code
= WXK_RETURN
; break;
186 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
187 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
188 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
189 case GDK_Delete
: key_code
= WXK_DELETE
; break;
190 case GDK_Home
: key_code
= WXK_HOME
; break;
191 case GDK_Left
: key_code
= WXK_LEFT
; break;
192 case GDK_Up
: key_code
= WXK_UP
; break;
193 case GDK_Right
: key_code
= WXK_RIGHT
; break;
194 case GDK_Down
: key_code
= WXK_DOWN
; break;
195 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
196 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
197 case GDK_Next
: key_code
= WXK_NEXT
; break;
198 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
199 case GDK_End
: key_code
= WXK_END
; break;
200 case GDK_Begin
: key_code
= WXK_HOME
; break;
201 case GDK_Select
: key_code
= WXK_SELECT
; break;
202 case GDK_Print
: key_code
= WXK_PRINT
; break;
203 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
204 case GDK_Insert
: key_code
= WXK_INSERT
; break;
205 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
206 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
207 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
208 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
209 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
210 case GDK_KP_Up
: key_code
= WXK_UP
; break;
211 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
212 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
213 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
214 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
215 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
216 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
217 case GDK_KP_End
: key_code
= WXK_END
; break;
218 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
219 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
220 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
221 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
222 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
223 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
224 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
225 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
226 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
227 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
228 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
229 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
230 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
231 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
232 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
233 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
234 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
235 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
236 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
237 case GDK_F1
: key_code
= WXK_F1
; break;
238 case GDK_F2
: key_code
= WXK_F2
; break;
239 case GDK_F3
: key_code
= WXK_F3
; break;
240 case GDK_F4
: key_code
= WXK_F4
; break;
241 case GDK_F5
: key_code
= WXK_F5
; break;
242 case GDK_F6
: key_code
= WXK_F6
; break;
243 case GDK_F7
: key_code
= WXK_F7
; break;
244 case GDK_F8
: key_code
= WXK_F8
; break;
245 case GDK_F9
: key_code
= WXK_F9
; break;
246 case GDK_F10
: key_code
= WXK_F10
; break;
247 case GDK_F11
: key_code
= WXK_F11
; break;
248 case GDK_F12
: key_code
= WXK_F12
; break;
251 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
252 key_code
= gdk_event
->keyval
;
256 if (!key_code
) return FALSE
;
258 wxKeyEvent
event( wxEVT_CHAR
);
259 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
260 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
261 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
262 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
263 event
.m_keyCode
= key_code
;
266 event
.SetEventObject( win
);
268 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
272 wxWindow
*ancestor
= win
;
275 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
278 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
279 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
282 ancestor
= ancestor
->GetParent();
288 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
289 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
295 //-----------------------------------------------------------------------------
296 // "button_press_event"
297 //-----------------------------------------------------------------------------
299 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
301 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
303 if ((g_captureWindow
) && (win
!= g_captureWindow
)) return TRUE
;
305 if (g_blockEventsOnDrag
) return TRUE
;
309 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
311 gtk_widget_grab_focus (win
->m_wxwindow
);
314 printf( "GrabFocus from " );
315 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
316 printf( win->GetClassInfo()->GetClassName() );
323 if (!win
->HasVMT()) return TRUE
;
326 printf( "OnButtonPress from " );
327 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
328 printf( win->GetClassInfo()->GetClassName() );
332 wxEventType event_type
= wxEVT_LEFT_DOWN
;
334 if (gdk_event
->button
== 1)
336 switch (gdk_event
->type
)
338 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
339 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
343 else if (gdk_event
->button
== 2)
345 switch (gdk_event
->type
)
347 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
348 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
352 else if (gdk_event
->button
== 3)
354 switch (gdk_event
->type
)
356 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
357 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
362 wxMouseEvent
event( event_type
);
363 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
364 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
365 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
366 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
367 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
368 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
369 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
371 event
.m_x
= (long)gdk_event
->x
;
372 event
.m_y
= (long)gdk_event
->y
;
374 // Some control don't have their own X window and thus cannot get
377 wxNode
*node
= win
->GetChildren()->First();
380 wxWindow
*child
= (wxWindow
*)node
->Data();
381 if ((child
->m_x
<= event
.m_x
) &&
382 (child
->m_y
<= event
.m_y
) &&
383 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
384 (child
->m_y
+child
->m_height
>= event
.m_y
))
387 event
.m_x
-= child
->m_x
;
388 event
.m_y
-= child
->m_y
;
394 event
.SetEventObject( win
);
396 if (win
->GetEventHandler()->ProcessEvent( event
))
397 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
402 //-----------------------------------------------------------------------------
403 // "button_release_event"
404 //-----------------------------------------------------------------------------
406 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
408 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
410 if ((g_captureWindow
) && (win
!= g_captureWindow
)) return TRUE
;
412 if (g_blockEventsOnDrag
) return TRUE
;
414 if (!win
->HasVMT()) return TRUE
;
417 printf( "OnButtonRelease from " );
418 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
419 printf( win->GetClassInfo()->GetClassName() );
423 wxEventType event_type
= wxEVT_NULL
;
425 switch (gdk_event
->button
)
427 case 1: event_type
= wxEVT_LEFT_UP
; break;
428 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
429 case 3: event_type
= wxEVT_RIGHT_UP
; break;
432 wxMouseEvent
event( event_type
);
433 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
434 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
435 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
436 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
437 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
438 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
439 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
440 event
.m_x
= (long)gdk_event
->x
;
441 event
.m_y
= (long)gdk_event
->y
;
443 // Some control don't have their own X window and thus cannot get
446 wxNode
*node
= win
->GetChildren()->First();
449 wxWindow
*child
= (wxWindow
*)node
->Data();
450 if ((child
->m_x
<= event
.m_x
) &&
451 (child
->m_y
<= event
.m_y
) &&
452 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
453 (child
->m_y
+child
->m_height
>= event
.m_y
))
456 event
.m_x
-= child
->m_x
;
457 event
.m_y
-= child
->m_y
;
463 event
.SetEventObject( win
);
465 if (win
->GetEventHandler()->ProcessEvent( event
))
466 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
471 //-----------------------------------------------------------------------------
472 // "motion_notify_event"
473 //-----------------------------------------------------------------------------
475 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
477 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
479 if ((g_captureWindow
) && (win
!= g_captureWindow
)) return TRUE
;
481 if (g_blockEventsOnDrag
) return TRUE
;
483 if (!win
->HasVMT()) return TRUE
;
486 printf( "OnMotion from " );
487 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
488 printf( win->GetClassInfo()->GetClassName() );
492 wxMouseEvent
event( wxEVT_MOTION
);
493 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
494 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
495 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
496 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
497 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
498 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
499 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
501 event
.m_x
= (long)gdk_event
->x
;
502 event
.m_y
= (long)gdk_event
->y
;
504 // Some control don't have their own X window and thus cannot get
507 wxNode
*node
= win
->GetChildren()->First();
510 wxWindow
*child
= (wxWindow
*)node
->Data();
511 if ((child
->m_x
<= event
.m_x
) &&
512 (child
->m_y
<= event
.m_y
) &&
513 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
514 (child
->m_y
+child
->m_height
>= event
.m_y
))
517 event
.m_x
-= child
->m_x
;
518 event
.m_y
-= child
->m_y
;
524 event
.SetEventObject( win
);
526 if (win
->GetEventHandler()->ProcessEvent( event
))
527 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
532 //-----------------------------------------------------------------------------
534 //-----------------------------------------------------------------------------
536 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
538 if (g_blockEventsOnDrag
) return TRUE
;
541 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
543 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
545 printf( "SetFocus flag from " );
546 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
547 printf( win->GetClassInfo()->GetClassName() );
553 if (!win
->HasVMT()) return TRUE
;
556 printf( "OnSetFocus from " );
557 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
558 printf( win->GetClassInfo()->GetClassName() );
560 printf( WXSTRINGCAST win->GetLabel() );
564 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
565 event
.SetEventObject( win
);
567 if (win
->GetEventHandler()->ProcessEvent( event
))
568 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
573 //-----------------------------------------------------------------------------
575 //-----------------------------------------------------------------------------
577 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
579 if (g_blockEventsOnDrag
) return TRUE
;
582 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
583 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
586 if (!win
->HasVMT()) return TRUE
;
589 printf( "OnKillFocus from " );
590 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
591 printf( win->GetClassInfo()->GetClassName() );
595 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
596 event
.SetEventObject( win
);
598 if (win
->GetEventHandler()->ProcessEvent( event
))
599 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
604 //-----------------------------------------------------------------------------
605 // "enter_notify_event"
606 //-----------------------------------------------------------------------------
608 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
610 if (widget
->window
!= gdk_event
->window
) return TRUE
;
612 if ((g_captureWindow
) && (win
!= g_captureWindow
)) return TRUE
;
614 if (g_blockEventsOnDrag
) return TRUE
;
616 if (!win
->HasVMT()) return TRUE
;
619 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
621 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
622 event
.SetEventObject( win
);
624 if (win
->GetEventHandler()->ProcessEvent( event
))
625 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
630 //-----------------------------------------------------------------------------
631 // "leave_notify_event"
632 //-----------------------------------------------------------------------------
634 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
636 if (widget
->window
!= gdk_event
->window
) return TRUE
;
638 if ((g_captureWindow
) && (win
!= g_captureWindow
)) return TRUE
;
640 if (g_blockEventsOnDrag
) return TRUE
;
642 if (!win
->HasVMT()) return TRUE
;
645 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
647 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
648 event
.SetEventObject( win
);
650 if (win
->GetEventHandler()->ProcessEvent( event
))
651 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
656 //-----------------------------------------------------------------------------
657 // "value_changed" from m_vAdjust
658 //-----------------------------------------------------------------------------
660 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
662 if (g_blockEventsOnDrag
) return;
665 printf( "OnVScroll from " );
666 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
667 printf( win->GetClassInfo()->GetClassName() );
671 if (!win
->HasVMT()) return;
673 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
674 if (fabs(diff
) < 0.2) return;
676 wxEventType command
= wxEVT_NULL
;
678 float line_step
= win
->m_vAdjust
->step_increment
;
679 float page_step
= win
->m_vAdjust
->page_increment
;
681 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
682 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
683 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
684 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
685 else command
= wxEVT_SCROLL_THUMBTRACK
;
687 int value
= (int)(win
->m_vAdjust
->value
+0.5);
689 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
690 event
.SetEventObject( win
);
691 win
->GetEventHandler()->ProcessEvent( event
);
694 //-----------------------------------------------------------------------------
695 // "value_changed" from m_hAdjust
696 //-----------------------------------------------------------------------------
698 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
700 if (g_blockEventsOnDrag
) return;
703 printf( "OnHScroll from " );
704 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
705 printf( win->GetClassInfo()->GetClassName() );
709 if (!win
->HasVMT()) return;
711 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
712 if (fabs(diff
) < 0.2) return;
714 wxEventType command
= wxEVT_NULL
;
716 float line_step
= win
->m_hAdjust
->step_increment
;
717 float page_step
= win
->m_hAdjust
->page_increment
;
719 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
720 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
721 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
722 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
723 else command
= wxEVT_SCROLL_THUMBTRACK
;
725 int value
= (int)(win
->m_hAdjust
->value
+0.5);
727 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
728 event
.SetEventObject( win
);
729 win
->GetEventHandler()->ProcessEvent( event
);
732 //-----------------------------------------------------------------------------
733 // "changed" from m_vAdjust
734 //-----------------------------------------------------------------------------
736 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
738 if (g_blockEventsOnDrag
) return;
741 printf( "OnVScroll change from " );
742 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
743 printf( win->GetClassInfo()->GetClassName() );
747 if (!win
->HasVMT()) return;
749 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
750 int value
= (int)(win
->m_vAdjust
->value
+0.5);
752 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
753 event
.SetEventObject( win
);
754 win
->GetEventHandler()->ProcessEvent( event
);
757 //-----------------------------------------------------------------------------
758 // "changed" from m_hAdjust
759 //-----------------------------------------------------------------------------
761 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
763 if (g_blockEventsOnDrag
) return;
766 printf( "OnHScroll change from " );
767 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
768 printf( win->GetClassInfo()->GetClassName() );
772 if (!win
->HasVMT()) return;
774 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
775 int value
= (int)(win
->m_hAdjust
->value
+0.5);
777 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
778 event
.SetEventObject( win
);
779 win
->GetEventHandler()->ProcessEvent( event
);
782 //-----------------------------------------------------------------------------
783 // "drop_data_available_event"
784 //-----------------------------------------------------------------------------
786 static void gtk_window_drop_callback( GtkWidget
*widget
, GdkEvent
*event
, wxWindow
*win
)
788 if (!win
->HasVMT()) return;
790 if (win
->GetDropTarget())
794 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
795 win
->GetDropTarget()->Drop( event
, x
, y
);
799 g_free (event->dropdataavailable.data);
800 g_free (event->dropdataavailable.data_type);
804 //-----------------------------------------------------------------------------
806 //-----------------------------------------------------------------------------
808 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
810 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
811 EVT_SIZE(wxWindow::OnSize
)
812 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
813 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
814 EVT_IDLE(wxWindow::OnIdle
)
819 m_widget
= (GtkWidget
*) NULL
;
820 m_wxwindow
= (GtkWidget
*) NULL
;
821 m_parent
= (wxWindow
*) NULL
;
822 m_children
.DeleteContents( FALSE
);
832 m_eventHandler
= this;
833 m_windowValidator
= (wxValidator
*) NULL
;
835 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
836 m_font
= *wxSWISS_FONT
;
838 m_windowName
= "noname";
839 m_constraints
= (wxLayoutConstraints
*) NULL
;
840 m_constraintsInvolvedIn
= (wxList
*) NULL
;
841 m_windowSizer
= (wxSizer
*) NULL
;
842 m_sizerParent
= (wxWindow
*) NULL
;
843 m_autoLayout
= FALSE
;
847 m_hasScrolling
= FALSE
;
848 m_hAdjust
= (GtkAdjustment
*) NULL
;
849 m_vAdjust
= (GtkAdjustment
*) NULL
;
850 m_oldHorizontalPos
= 0.0;
851 m_oldVerticalPos
= 0.0;
854 m_pDropTarget
= (wxDropTarget
*) NULL
;
856 m_hasOwnStyle
= FALSE
;
859 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
860 const wxPoint
&pos
, const wxSize
&size
,
861 long style
, const wxString
&name
)
867 m_cursor
= (wxCursor
*) NULL
;
869 PreCreation( parent
, id
, pos
, size
, style
, name
);
871 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
872 m_hasScrolling
= TRUE
;
874 GtkScrolledWindow
*s_window
;
875 s_window
= GTK_SCROLLED_WINDOW(m_widget
);
877 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
878 scroll_class
->scrollbar_spacing
= 0;
880 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
882 m_oldHorizontalPos
= 0.0;
883 m_oldVerticalPos
= 0.0;
885 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
886 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
888 gtk_signal_connect (GTK_OBJECT (m_hAdjust
), "value_changed",
889 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
890 gtk_signal_connect (GTK_OBJECT (m_vAdjust
), "value_changed",
891 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
893 gtk_signal_connect (GTK_OBJECT (m_hAdjust
), "changed",
894 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
895 gtk_signal_connect (GTK_OBJECT (m_vAdjust
), "changed",
896 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
898 GtkViewport
*viewport
;
899 viewport
= GTK_VIEWPORT(s_window
->viewport
);
901 if (m_windowStyle
& wxRAISED_BORDER
)
903 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
905 else if (m_windowStyle
& wxSUNKEN_BORDER
)
907 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
911 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
914 m_wxwindow
= gtk_myfixed_new();
916 if (m_wxwindow
) GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
918 if (m_windowStyle
& wxTAB_TRAVERSAL
== wxTAB_TRAVERSAL
)
919 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
921 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
923 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
925 // shut the viewport up
926 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
927 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
929 // I _really_ don't want scrollbars in the beginning
930 m_vAdjust
->lower
= 0.0;
931 m_vAdjust
->upper
= 1.0;
932 m_vAdjust
->value
= 0.0;
933 m_vAdjust
->step_increment
= 1.0;
934 m_vAdjust
->page_increment
= 1.0;
935 m_vAdjust
->page_size
= 5.0;
936 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
937 m_hAdjust
->lower
= 0.0;
938 m_hAdjust
->upper
= 1.0;
939 m_hAdjust
->value
= 0.0;
940 m_hAdjust
->step_increment
= 1.0;
941 m_hAdjust
->page_increment
= 1.0;
942 m_hAdjust
->page_size
= 5.0;
943 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
945 gtk_widget_show( m_wxwindow
);
954 wxWindow::~wxWindow(void)
958 if (m_pDropTarget
) delete m_pDropTarget
;
960 if (m_parent
) m_parent
->RemoveChild( this );
961 if (m_widget
) Show( FALSE
);
965 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
967 if (m_widget
) gtk_widget_destroy( m_widget
);
971 DeleteRelatedConstraints();
974 // This removes any dangling pointers to this window
975 // in other windows' constraintsInvolvedIn lists.
976 UnsetConstraints(m_constraints
);
977 delete m_constraints
;
978 m_constraints
= (wxLayoutConstraints
*) NULL
;
982 delete m_windowSizer
;
983 m_windowSizer
= (wxSizer
*) NULL
;
985 // If this is a child of a sizer, remove self from parent
986 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
988 // Just in case the window has been Closed, but
989 // we're then deleting immediately: don't leave
990 // dangling pointers.
991 wxPendingDelete
.DeleteObject(this);
993 // Just in case we've loaded a top-level window via
994 // wxWindow::LoadNativeDialog but we weren't a dialog
996 wxTopLevelWindows
.DeleteObject(this);
998 if (m_windowValidator
) delete m_windowValidator
;
1001 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1002 const wxPoint
&pos
, const wxSize
&size
,
1003 long style
, const wxString
&name
)
1005 if (m_needParent
&& (parent
== NULL
))
1006 wxFatalError( "Need complete parent.", name
);
1008 m_widget
= (GtkWidget
*) NULL
;
1011 m_children
.DeleteContents( FALSE
);
1015 if (m_width
== -1) m_width
= 20;
1017 if (m_height
== -1) m_height
= 20;
1023 m_eventHandler
= this;
1026 if (m_cursor
== NULL
)
1027 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1028 m_font
= *wxSWISS_FONT
;
1029 m_backgroundColour
= wxWHITE
;
1030 m_foregroundColour
= wxBLACK
;
1031 m_windowStyle
= style
;
1032 m_windowName
= name
;
1033 m_constraints
= (wxLayoutConstraints
*) NULL
;
1034 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1035 m_windowSizer
= (wxSizer
*) NULL
;
1036 m_sizerParent
= (wxWindow
*) NULL
;
1037 m_autoLayout
= FALSE
;
1038 m_pDropTarget
= (wxDropTarget
*) NULL
;
1040 m_windowValidator
= (wxValidator
*) NULL
;
1041 m_hasOwnStyle
= FALSE
;
1044 void wxWindow::PostCreation(void)
1046 if (m_parent
) m_parent
->AddChild( this );
1050 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1051 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1053 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1054 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1057 ConnectWidget( GetConnectWidget() );
1059 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1063 gtk_widget_realize( m_wxwindow
);
1064 gdk_gc_set_exposures( m_wxwindow
->style
->fg_gc
[0], TRUE
);
1067 SetCursor( wxSTANDARD_CURSOR
);
1072 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1074 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1075 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1077 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1078 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1080 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1081 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1083 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1084 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1086 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1087 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1089 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1090 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1092 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1093 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1095 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1096 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1099 bool wxWindow::HasVMT(void)
1104 bool wxWindow::Close( bool force
)
1106 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1107 event
.SetEventObject(this);
1108 event
.SetForce(force
);
1110 return GetEventHandler()->ProcessEvent(event
);
1113 bool wxWindow::Destroy(void)
1120 bool wxWindow::DestroyChildren(void)
1125 while ((node
= GetChildren()->First()) != (wxNode
*)NULL
)
1128 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1131 if (GetChildren()->Member(child
)) delete node
;
1138 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1140 // are we to set fonts here ?
1143 void wxWindow::ImplementSetSize(void)
1145 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1146 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1147 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_minWidth
;
1148 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_minHeight
;
1149 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1152 void wxWindow::ImplementSetPosition(void)
1154 if (IS_KIND_OF(this,wxFrame
) || IS_KIND_OF(this,wxDialog
))
1156 if ((m_x
!= -1) || (m_y
!= -1))
1157 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
1163 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1167 if ((m_parent
) && (m_parent
->m_wxwindow
))
1168 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
, m_y
);
1170 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1173 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1175 if (m_resizing
) return; // I don't like recursions
1183 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1185 if (newX
== -1) newX
= m_x
;
1186 if (newY
== -1) newY
= m_y
;
1187 if (newW
== -1) newW
= m_width
;
1188 if (newH
== -1) newH
= m_height
;
1191 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1193 if (newW
== -1) newW
= 80;
1196 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1198 if (newH
== -1) newH
= 26;
1201 if ((m_x
!= newX
) || (m_y
!= newY
) || (!m_sizeSet
))
1205 ImplementSetPosition();
1207 if ((m_width
!= newW
) || (m_height
!= newH
) || (!m_sizeSet
))
1215 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1216 event
.SetEventObject( this );
1217 ProcessEvent( event
);
1222 void wxWindow::SetSize( int width
, int height
)
1224 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1227 void wxWindow::Move( int x
, int y
)
1229 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1232 void wxWindow::GetSize( int *width
, int *height
) const
1234 if (width
) (*width
) = m_width
;
1235 if (height
) (*height
) = m_height
;
1238 void wxWindow::SetClientSize( int width
, int height
)
1242 SetSize( width
, height
);
1249 if (!m_hasScrolling
)
1252 do we have sunken dialogs ?
1254 GtkStyleClass *window_class = m_wxwindow->style->klass;
1256 dw += 2 * window_class->xthickness;
1257 dh += 2 * window_class->ythickness;
1262 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1263 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1265 GtkWidget
*viewport
= scroll_window
->viewport
;
1266 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1268 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1269 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1271 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1272 (m_windowStyle
& wxSUNKEN_BORDER
))
1274 dw
+= 2 * viewport_class
->xthickness
;
1275 dh
+= 2 * viewport_class
->ythickness
;
1278 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1280 dw
+= vscrollbar
->allocation
.width
;
1281 dw
+= scroll_class
->scrollbar_spacing
;
1284 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1286 dh
+= hscrollbar
->allocation
.height
;
1287 dw
+= scroll_class
->scrollbar_spacing
;
1291 SetSize( width
+dw
, height
+dh
);
1295 void wxWindow::GetClientSize( int *width
, int *height
) const
1299 if (width
) (*width
) = m_width
;
1300 if (height
) (*height
) = m_height
;
1307 if (!m_hasScrolling
)
1310 do we have sunken dialogs ?
1312 GtkStyleClass *window_class = m_wxwindow->style->klass;
1314 dw += 2 * window_class->xthickness;
1315 dh += 2 * window_class->ythickness;
1320 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1321 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1323 GtkWidget
*viewport
= scroll_window
->viewport
;
1324 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1326 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1327 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1329 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1330 (m_windowStyle
& wxSUNKEN_BORDER
))
1332 dw
+= 2 * viewport_class
->xthickness
;
1333 dh
+= 2 * viewport_class
->ythickness
;
1336 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1338 // dw += vscrollbar->allocation.width;
1339 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1340 dw
+= scroll_class
->scrollbar_spacing
;
1343 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1345 // dh += hscrollbar->allocation.height;
1347 dh
+= scroll_class
->scrollbar_spacing
;
1351 if (width
) (*width
) = m_width
- dw
;
1352 if (height
) (*height
) = m_height
- dh
;
1356 void wxWindow::GetPosition( int *x
, int *y
) const
1362 void wxWindow::ClientToScreen( int *x
, int *y
)
1364 GdkWindow
*source
= (GdkWindow
*) NULL
;
1366 source
= m_wxwindow
->window
;
1368 source
= m_widget
->window
;
1372 gdk_window_get_origin( source
, &org_x
, &org_y
);
1376 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1378 org_x
+= m_widget
->allocation
.x
;
1379 org_y
+= m_widget
->allocation
.y
;
1387 void wxWindow::ScreenToClient( int *x
, int *y
)
1389 GdkWindow
*source
= (GdkWindow
*) NULL
;
1391 source
= m_wxwindow
->window
;
1393 source
= m_widget
->window
;
1397 gdk_window_get_origin( source
, &org_x
, &org_y
);
1401 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1403 org_x
+= m_widget
->allocation
.x
;
1404 org_y
+= m_widget
->allocation
.y
;
1412 void wxWindow::Centre( int direction
)
1414 if (IS_KIND_OF(this,wxDialog
) || IS_KIND_OF(this,wxFrame
))
1416 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (gdk_screen_width () - m_width
) / 2;
1417 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (gdk_screen_height () - m_height
) / 2;
1418 ImplementSetPosition();
1426 m_parent
->GetSize( &p_w
, &p_h
);
1427 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (p_w
- m_width
) / 2;
1428 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (p_h
- m_height
) / 2;
1429 ImplementSetPosition();
1434 void wxWindow::Fit(void)
1438 wxNode
*node
= GetChildren()->First();
1441 wxWindow
*win
= (wxWindow
*)node
->Data();
1443 win
->GetPosition(&wx
, &wy
);
1444 win
->GetSize(&ww
, &wh
);
1445 if ( wx
+ ww
> maxX
)
1447 if ( wy
+ wh
> maxY
)
1450 node
= node
->Next();
1452 SetClientSize(maxX
+ 5, maxY
+ 10);
1455 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1463 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1465 //if (GetAutoLayout()) Layout();
1468 bool wxWindow::Show( bool show
)
1471 gtk_widget_show( m_widget
);
1473 gtk_widget_hide( m_widget
);
1478 void wxWindow::Enable( bool enable
)
1480 m_isEnabled
= enable
;
1481 gtk_widget_set_sensitive( m_widget
, enable
);
1482 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1485 int wxWindow::GetCharHeight(void) const
1487 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1488 return font
->ascent
+ font
->descent
;
1491 int wxWindow::GetCharWidth(void) const
1493 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1494 return gdk_string_width( font
, "H" );
1497 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1498 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1500 wxFont fontToUse
= m_font
;
1501 if (theFont
) fontToUse
= *theFont
;
1503 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1504 if (x
) (*x
) = gdk_string_width( font
, string
);
1505 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1506 if (descent
) (*descent
) = font
->descent
;
1507 if (externalLeading
) (*externalLeading
) = 0; // ??
1510 void wxWindow::MakeModal( bool modal
)
1513 // Disable all other windows
1514 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1516 wxNode
*node
= wxTopLevelWindows
.First();
1519 wxWindow
*win
= (wxWindow
*)node
->Data();
1521 win
->Enable(!modal
);
1523 node
= node
->Next();
1528 void wxWindow::SetFocus(void)
1530 GtkWidget
*connect_widget
= GetConnectWidget();
1533 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) && !GTK_WIDGET_HAS_FOCUS (connect_widget
) )
1535 gtk_widget_grab_focus (connect_widget
);
1540 bool wxWindow::OnClose(void)
1545 void wxWindow::AddChild( wxWindow
*child
)
1547 // Addchild is (often) called before the program
1548 // has left the parents constructor so that no
1549 // virtual tables work yet. The approach below
1550 // practically imitates virtual tables, i.e. it
1551 // implements a different AddChild() behaviour
1552 // for wxFrame, wxDialog, wxWindow and
1553 // wxMDIParentFrame.
1555 // wxFrame and wxDialog as children aren't placed into the parents
1557 if (( IS_KIND_OF(child
,wxFrame
) || IS_KIND_OF(child
,wxDialog
) ) &&
1558 (!IS_KIND_OF(child
,wxMDIChildFrame
)))
1560 m_children
.Append( child
);
1562 if ((child
->m_x
!= -1) && (child
->m_y
!= -1))
1563 gtk_widget_set_uposition( child
->m_widget
, child
->m_x
, child
->m_y
);
1568 // In the case of an wxMDIChildFrame descendant, we use the
1569 // client windows's AddChild()
1571 if (IS_KIND_OF(this,wxMDIParentFrame
))
1573 if (IS_KIND_OF(child
,wxMDIChildFrame
))
1575 wxMDIClientWindow
*client
= ((wxMDIParentFrame
*)this)->GetClientWindow();
1578 client
->AddChild( child
);
1584 // wxNotebook is very special, so it has a private AddChild()
1586 if (IS_KIND_OF(this,wxNotebook
))
1588 wxNotebook
*tab
= (wxNotebook
*)this;
1589 tab
->AddChild( child
);
1593 // wxFrame has a private AddChild
1595 if (IS_KIND_OF(this,wxFrame
) && !IS_KIND_OF(this,wxMDIChildFrame
))
1597 wxFrame
*frame
= (wxFrame
*)this;
1598 frame
->AddChild( child
);
1604 m_children
.Append( child
);
1605 if (m_wxwindow
) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), child
->m_widget
,
1606 child
->m_x
, child
->m_y
);
1608 gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height
);
1611 wxList
*wxWindow::GetChildren(void)
1613 return (&m_children
);
1616 void wxWindow::RemoveChild( wxWindow
*child
)
1619 GetChildren()->DeleteObject( child
);
1620 child
->m_parent
= (wxWindow
*) NULL
;
1623 void wxWindow::SetReturnCode( int retCode
)
1625 m_retCode
= retCode
;
1628 int wxWindow::GetReturnCode(void)
1633 void wxWindow::Raise(void)
1635 if (m_widget
) gdk_window_raise( m_widget
->window
);
1638 void wxWindow::Lower(void)
1640 if (m_widget
) gdk_window_lower( m_widget
->window
);
1643 wxEvtHandler
*wxWindow::GetEventHandler(void)
1645 return m_eventHandler
;
1648 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
1650 m_eventHandler
= handler
;
1653 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
1655 handler
->SetNextHandler(GetEventHandler());
1656 SetEventHandler(handler
);
1659 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
1661 if ( GetEventHandler() )
1663 wxEvtHandler
*handlerA
= GetEventHandler();
1664 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
1665 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
1666 SetEventHandler(handlerB
);
1667 if ( deleteHandler
)
1670 return (wxEvtHandler
*) NULL
;
1676 return (wxEvtHandler
*) NULL
;
1679 wxValidator
*wxWindow::GetValidator(void)
1681 return m_windowValidator
;
1684 void wxWindow::SetValidator( const wxValidator
& validator
)
1686 if (m_windowValidator
) delete m_windowValidator
;
1687 m_windowValidator
= validator
.Clone();
1688 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
1691 bool wxWindow::IsBeingDeleted(void)
1696 void wxWindow::SetId( wxWindowID id
)
1701 wxWindowID
wxWindow::GetId(void)
1706 void wxWindow::SetCursor( const wxCursor
&cursor
)
1708 wxASSERT(m_cursor
!= NULL
);
1710 if (m_cursor
!= NULL
)
1711 if (*m_cursor
== cursor
)
1713 (*m_cursor
) = cursor
;
1714 if (m_widget
->window
)
1715 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
1716 if (m_wxwindow
&& m_wxwindow
->window
)
1717 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
1720 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
1722 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
1725 gdk_window_clear_area( m_wxwindow
->window
,
1739 GetClientSize( &w
, &h
);
1741 GdkRectangle gdk_rect
;
1745 gdk_rect
.height
= h
;
1746 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1751 GdkRectangle gdk_rect
;
1752 gdk_rect
.x
= rect
->x
;
1753 gdk_rect
.y
= rect
->y
;
1754 gdk_rect
.width
= rect
->width
;
1755 gdk_rect
.height
= rect
->height
;
1758 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1760 gtk_widget_draw( m_widget
, &gdk_rect
);
1764 wxRegion
wxWindow::GetUpdateRegion() const
1766 return m_updateRegion
;
1769 bool wxWindow::IsExposed( int x
, int y
) const
1771 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
1774 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
1776 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
1779 bool wxWindow::IsExposed( const wxPoint
& pt
) const
1781 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
1784 bool wxWindow::IsExposed( const wxRect
& rect
) const
1786 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
1789 void wxWindow::Clear(void)
1791 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
1794 wxColour
wxWindow::GetBackgroundColour(void) const
1796 return m_backgroundColour
;
1799 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
1801 m_backgroundColour
= colour
;
1804 m_backgroundColour
.CalcPixel( m_wxwindow
->style
->colormap
);
1805 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
1806 gdk_window_clear( m_wxwindow
->window
);
1811 wxColour
wxWindow::GetForegroundColour(void) const
1813 return m_foregroundColour
;
1816 void wxWindow::SetForegroundColour( const wxColour
&colour
)
1818 m_foregroundColour
= colour
;
1821 bool wxWindow::Validate(void)
1823 wxNode
*node
= GetChildren()->First();
1826 wxWindow
*child
= (wxWindow
*)node
->Data();
1827 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
1829 node
= node
->Next();
1834 bool wxWindow::TransferDataToWindow(void)
1836 wxNode
*node
= GetChildren()->First();
1839 wxWindow
*child
= (wxWindow
*)node
->Data();
1840 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
1841 !child
->GetValidator()->TransferToWindow() )
1843 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
1846 node
= node
->Next();
1851 bool wxWindow::TransferDataFromWindow(void)
1853 wxNode
*node
= GetChildren()->First();
1856 wxWindow
*child
= (wxWindow
*)node
->Data();
1857 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
1859 node
= node
->Next();
1864 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
1866 m_acceleratorTable
= accel
;
1869 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
1871 TransferDataToWindow();
1874 void wxWindow::InitDialog(void)
1876 wxInitDialogEvent
event(GetId());
1877 event
.SetEventObject( this );
1878 GetEventHandler()->ProcessEvent(event
);
1881 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
1883 menu
->SetInvokingWindow( win
);
1884 wxNode
*node
= menu
->m_items
.First();
1887 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
1888 if (menuitem
->IsSubMenu())
1889 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
1890 node
= node
->Next();
1894 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
1896 SetInvokingWindow( menu
, this );
1897 gtk_menu_popup( GTK_MENU(menu
->m_menu
), (GtkWidget
*) NULL
, (GtkWidget
*) NULL
, (GtkMenuPositionFunc
) NULL
, NULL
, 0, 0 );
1901 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
1903 GtkWidget
*dnd_widget
= GetConnectWidget();
1905 DisconnectDnDWidget( dnd_widget
);
1907 if (m_pDropTarget
) delete m_pDropTarget
;
1908 m_pDropTarget
= dropTarget
;
1910 ConnectDnDWidget( dnd_widget
);
1913 wxDropTarget
*wxWindow::GetDropTarget() const
1915 return m_pDropTarget
;
1918 void wxWindow::ConnectDnDWidget( GtkWidget
*widget
)
1920 if (!m_pDropTarget
) return;
1922 m_pDropTarget
->RegisterWidget( widget
);
1924 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
1925 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
1928 void wxWindow::DisconnectDnDWidget( GtkWidget
*widget
)
1930 if (!m_pDropTarget
) return;
1932 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
1933 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
1935 m_pDropTarget
->UnregisterWidget( widget
);
1938 GtkWidget
* wxWindow::GetConnectWidget(void)
1940 GtkWidget
*connect_widget
= m_widget
;
1941 if (m_wxwindow
) connect_widget
= m_wxwindow
;
1943 return connect_widget
;
1946 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
1948 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
1949 return (window
== m_widget
->window
);
1952 void wxWindow::SetFont( const wxFont
&font
)
1954 if (((wxFont
*)&font
)->Ok())
1957 m_font
= *wxSWISS_FONT
;
1959 GtkStyle
*style
= (GtkStyle
*) NULL
;
1962 m_hasOwnStyle
= TRUE
;
1963 style
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
1967 style
= gtk_widget_get_style( m_widget
);
1970 gdk_font_unref( style
->font
);
1971 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
1973 gtk_widget_set_style( m_widget
, style
);
1976 wxFont
*wxWindow::GetFont(void)
1981 void wxWindow::SetWindowStyleFlag( long flag
)
1983 m_windowStyle
= flag
;
1986 long wxWindow::GetWindowStyleFlag(void) const
1988 return m_windowStyle
;
1991 void wxWindow::CaptureMouse(void)
1993 GtkWidget
*connect_widget
= GetConnectWidget();
1994 gtk_grab_add( connect_widget
);
1995 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
1997 (GDK_BUTTON_PRESS_MASK
|
1998 GDK_BUTTON_RELEASE_MASK
|
1999 GDK_POINTER_MOTION_MASK
),
2000 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
2001 g_captureWindow
= this;
2004 void wxWindow::ReleaseMouse(void)
2006 GtkWidget
*connect_widget
= GetConnectWidget();
2007 gtk_grab_remove( connect_widget
);
2008 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2009 g_captureWindow
= (wxWindow
*) NULL
;;
2012 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2016 wxString
wxWindow::GetTitle(void) const
2018 return (wxString
&)m_windowName
;
2021 wxString
wxWindow::GetLabel(void) const
2026 void wxWindow::SetName( const wxString
&name
)
2028 m_windowName
= name
;
2031 wxString
wxWindow::GetName(void) const
2033 return (wxString
&)m_windowName
;
2036 bool wxWindow::IsShown(void) const
2041 bool wxWindow::IsRetained(void)
2046 wxWindow
*wxWindow::FindWindow( long id
)
2048 if (id
== m_windowId
) return this;
2049 wxNode
*node
= m_children
.First();
2052 wxWindow
*child
= (wxWindow
*)node
->Data();
2053 wxWindow
*res
= child
->FindWindow( id
);
2054 if (res
) return res
;
2055 node
= node
->Next();
2057 return (wxWindow
*) NULL
;
2060 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2062 if (name
== m_windowName
) return this;
2063 wxNode
*node
= m_children
.First();
2066 wxWindow
*child
= (wxWindow
*)node
->Data();
2067 wxWindow
*res
= child
->FindWindow( name
);
2068 if (res
) return res
;
2069 node
= node
->Next();
2071 return (wxWindow
*) NULL
;
2074 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2075 int range
, bool WXUNUSED(refresh
) )
2077 if (!m_wxwindow
) return;
2079 if (orient
== wxHORIZONTAL
)
2081 float fpos
= (float)pos
;
2082 m_oldHorizontalPos
= fpos
;
2083 float frange
= (float)range
;
2084 float fthumb
= (float)thumbVisible
;
2086 if ((fabs(fpos
-m_hAdjust
->value
) < 0.2) &&
2087 (fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2088 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2091 m_hAdjust
->lower
= 0.0;
2092 m_hAdjust
->upper
= frange
;
2093 m_hAdjust
->value
= fpos
;
2094 m_hAdjust
->step_increment
= 1.0;
2095 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2096 m_hAdjust
->page_size
= fthumb
;
2100 float fpos
= (float)pos
;
2101 m_oldVerticalPos
= fpos
;
2102 float frange
= (float)range
;
2103 float fthumb
= (float)thumbVisible
;
2105 if ((fabs(fpos
-m_vAdjust
->value
) < 0.2) &&
2106 (fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2107 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2110 m_vAdjust
->lower
= 0.0;
2111 m_vAdjust
->upper
= frange
;
2112 m_vAdjust
->value
= fpos
;
2113 m_vAdjust
->step_increment
= 1.0;
2114 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2115 m_vAdjust
->page_size
= fthumb
;
2118 if (m_wxwindow
->window
)
2120 if (orient
== wxHORIZONTAL
)
2121 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2123 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2125 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2129 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2131 if (!m_wxwindow
) return;
2133 if (orient
== wxHORIZONTAL
)
2135 float fpos
= (float)pos
;
2136 m_oldHorizontalPos
= fpos
;
2138 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2139 m_hAdjust
->value
= fpos
;
2143 float fpos
= (float)pos
;
2144 m_oldVerticalPos
= fpos
;
2145 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2146 m_vAdjust
->value
= fpos
;
2149 if (m_wxwindow
->window
)
2151 if (orient
== wxHORIZONTAL
)
2152 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2154 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2158 int wxWindow::GetScrollThumb( int orient
) const
2160 if (!m_wxwindow
) return 0;
2162 if (orient
== wxHORIZONTAL
)
2163 return (int)(m_hAdjust
->page_size
+0.5);
2165 return (int)(m_vAdjust
->page_size
+0.5);
2168 int wxWindow::GetScrollPos( int orient
) const
2170 if (!m_wxwindow
) return 0;
2172 if (orient
== wxHORIZONTAL
)
2173 return (int)(m_hAdjust
->value
+0.5);
2175 return (int)(m_vAdjust
->value
+0.5);
2178 int wxWindow::GetScrollRange( int orient
) const
2180 if (!m_wxwindow
) return 0;
2182 if (orient
== wxHORIZONTAL
)
2183 return (int)(m_hAdjust
->upper
+0.5);
2185 return (int)(m_vAdjust
->upper
+0.5);
2188 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2190 if (!m_wxwindow
) return;
2193 bool refresh = FALSE;
2195 if ((m_drawingOffsetX == 0) && (m_drawingOffsetY == 0))
2197 m_drawingOffsetX = -16000;
2198 m_drawingOffsetY = -16000;
2203 m_drawingOffsetX += dx;
2204 m_drawingOffsetY += dy;
2207 // printf( "X: %d Y: %d \n", (int)m_drawingOffsetX, (int)m_drawingOffsetY );
2209 gtk_myfixed_set_offset( GTK_MYFIXED(m_wxwindow), m_drawingOffsetX, m_drawingOffsetY );
2211 if (refresh) Refresh();
2213 The code here is very nifty, but it doesn't work with
2214 overlapping windows...
2219 GetClientSize( &cw
, &ch
);
2221 int w
= cw
- abs(dx
);
2222 int h
= ch
- abs(dy
);
2223 if ((h
< 0) || (w
< 0))
2230 if (dx
< 0) s_x
= -dx
;
2231 if (dy
< 0) s_y
= -dy
;
2234 if (dx
> 0) d_x
= dx
;
2235 if (dy
> 0) d_y
= dy
;
2236 gdk_window_copy_area( m_wxwindow
->window
, m_wxwindow
->style
->fg_gc
[0], d_x
, d_y
,
2237 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2240 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2241 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2242 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2243 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2245 Refresh( TRUE
, &rect
);
2248 //-------------------------------------------------------------------------------------
2250 //-------------------------------------------------------------------------------------
2252 wxLayoutConstraints
*wxWindow::GetConstraints(void) const
2254 return m_constraints
;
2257 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2261 UnsetConstraints(m_constraints
);
2262 delete m_constraints
;
2264 m_constraints
= constraints
;
2267 // Make sure other windows know they're part of a 'meaningful relationship'
2268 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2269 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2270 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2271 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2272 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2273 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2274 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2275 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2276 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2277 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2278 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2279 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2280 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2281 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2282 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2283 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2289 void wxWindow::SetAutoLayout( bool autoLayout
)
2291 m_autoLayout
= autoLayout
;
2294 bool wxWindow::GetAutoLayout(void) const
2296 return m_autoLayout
;
2299 wxSizer
*wxWindow::GetSizer(void) const
2301 return m_windowSizer
;
2304 void wxWindow::SetSizerParent( wxWindow
*win
)
2306 m_sizerParent
= win
;
2309 wxWindow
*wxWindow::GetSizerParent(void) const
2311 return m_sizerParent
;
2314 // This removes any dangling pointers to this window
2315 // in other windows' constraintsInvolvedIn lists.
2316 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2320 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2321 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2322 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2323 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2324 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2325 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2326 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2327 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2328 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2329 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2330 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2331 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2332 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2333 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2334 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2335 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2339 // Back-pointer to other windows we're involved with, so if we delete
2340 // this window, we must delete any constraints we're involved with.
2341 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2343 if (!m_constraintsInvolvedIn
)
2344 m_constraintsInvolvedIn
= new wxList
;
2345 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2346 m_constraintsInvolvedIn
->Append(otherWin
);
2349 // REMOVE back-pointer to other windows we're involved with.
2350 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2352 if (m_constraintsInvolvedIn
)
2353 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2356 // Reset any constraints that mention this window
2357 void wxWindow::DeleteRelatedConstraints(void)
2359 if (m_constraintsInvolvedIn
)
2361 wxNode
*node
= m_constraintsInvolvedIn
->First();
2364 wxWindow
*win
= (wxWindow
*)node
->Data();
2365 wxNode
*next
= node
->Next();
2366 wxLayoutConstraints
*constr
= win
->GetConstraints();
2368 // Reset any constraints involving this window
2371 constr
->left
.ResetIfWin((wxWindow
*)this);
2372 constr
->top
.ResetIfWin((wxWindow
*)this);
2373 constr
->right
.ResetIfWin((wxWindow
*)this);
2374 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2375 constr
->width
.ResetIfWin((wxWindow
*)this);
2376 constr
->height
.ResetIfWin((wxWindow
*)this);
2377 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2378 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2383 delete m_constraintsInvolvedIn
;
2384 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2388 void wxWindow::SetSizer(wxSizer
*sizer
)
2390 m_windowSizer
= sizer
;
2392 sizer
->SetSizerParent((wxWindow
*)this);
2399 bool wxWindow::Layout(void)
2401 if (GetConstraints())
2404 GetClientSize(&w
, &h
);
2405 GetConstraints()->width
.SetValue(w
);
2406 GetConstraints()->height
.SetValue(h
);
2409 // If top level (one sizer), evaluate the sizer's constraints.
2413 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2414 GetSizer()->LayoutPhase1(&noChanges
);
2415 GetSizer()->LayoutPhase2(&noChanges
);
2416 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2421 // Otherwise, evaluate child constraints
2422 ResetConstraints(); // Mark all constraints as unevaluated
2423 DoPhase(1); // Just one phase need if no sizers involved
2425 SetConstraintSizes(); // Recursively set the real window sizes
2431 // Do a phase of evaluating constraints:
2432 // the default behaviour. wxSizers may do a similar
2433 // thing, but also impose their own 'constraints'
2434 // and order the evaluation differently.
2435 bool wxWindow::LayoutPhase1(int *noChanges
)
2437 wxLayoutConstraints
*constr
= GetConstraints();
2440 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2446 bool wxWindow::LayoutPhase2(int *noChanges
)
2456 // Do a phase of evaluating child constraints
2457 bool wxWindow::DoPhase(int phase
)
2459 int noIterations
= 0;
2460 int maxIterations
= 500;
2464 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2468 wxNode
*node
= GetChildren()->First();
2471 wxWindow
*child
= (wxWindow
*)node
->Data();
2472 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2474 wxLayoutConstraints
*constr
= child
->GetConstraints();
2477 if (succeeded
.Member(child
))
2482 int tempNoChanges
= 0;
2483 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2484 noChanges
+= tempNoChanges
;
2487 succeeded
.Append(child
);
2492 node
= node
->Next();
2499 void wxWindow::ResetConstraints(void)
2501 wxLayoutConstraints
*constr
= GetConstraints();
2504 constr
->left
.SetDone(FALSE
);
2505 constr
->top
.SetDone(FALSE
);
2506 constr
->right
.SetDone(FALSE
);
2507 constr
->bottom
.SetDone(FALSE
);
2508 constr
->width
.SetDone(FALSE
);
2509 constr
->height
.SetDone(FALSE
);
2510 constr
->centreX
.SetDone(FALSE
);
2511 constr
->centreY
.SetDone(FALSE
);
2513 wxNode
*node
= GetChildren()->First();
2516 wxWindow
*win
= (wxWindow
*)node
->Data();
2517 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2518 win
->ResetConstraints();
2519 node
= node
->Next();
2523 // Need to distinguish between setting the 'fake' size for
2524 // windows and sizers, and setting the real values.
2525 void wxWindow::SetConstraintSizes(bool recurse
)
2527 wxLayoutConstraints
*constr
= GetConstraints();
2528 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2529 constr
->width
.GetDone() && constr
->height
.GetDone())
2531 int x
= constr
->left
.GetValue();
2532 int y
= constr
->top
.GetValue();
2533 int w
= constr
->width
.GetValue();
2534 int h
= constr
->height
.GetValue();
2536 // If we don't want to resize this window, just move it...
2537 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2538 (constr
->height
.GetRelationship() != wxAsIs
))
2540 // Calls Layout() recursively. AAAGH. How can we stop that.
2541 // Simply take Layout() out of non-top level OnSizes.
2542 SizerSetSize(x
, y
, w
, h
);
2551 char *windowClass
= this->GetClassInfo()->GetClassName();
2554 if (GetName() == "")
2555 winName
= _("unnamed");
2557 winName
= GetName();
2558 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2559 if (!constr
->left
.GetDone())
2560 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2561 if (!constr
->right
.GetDone())
2562 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2563 if (!constr
->width
.GetDone())
2564 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2565 if (!constr
->height
.GetDone())
2566 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2567 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2572 wxNode
*node
= GetChildren()->First();
2575 wxWindow
*win
= (wxWindow
*)node
->Data();
2576 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2577 win
->SetConstraintSizes();
2578 node
= node
->Next();
2583 // This assumes that all sizers are 'on' the same
2584 // window, i.e. the parent of this window.
2585 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2587 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2588 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2592 m_sizerParent
->GetPosition(&xp
, &yp
);
2593 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2598 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2602 TransformSizerToActual(&xx
, &yy
);
2603 SetSize(xx
, yy
, w
, h
);
2606 void wxWindow::SizerMove(int x
, int y
)
2610 TransformSizerToActual(&xx
, &yy
);
2614 // Only set the size/position of the constraint (if any)
2615 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2617 wxLayoutConstraints
*constr
= GetConstraints();
2622 constr
->left
.SetValue(x
);
2623 constr
->left
.SetDone(TRUE
);
2627 constr
->top
.SetValue(y
);
2628 constr
->top
.SetDone(TRUE
);
2632 constr
->width
.SetValue(w
);
2633 constr
->width
.SetDone(TRUE
);
2637 constr
->height
.SetValue(h
);
2638 constr
->height
.SetDone(TRUE
);
2643 void wxWindow::MoveConstraint(int x
, int y
)
2645 wxLayoutConstraints
*constr
= GetConstraints();
2650 constr
->left
.SetValue(x
);
2651 constr
->left
.SetDone(TRUE
);
2655 constr
->top
.SetValue(y
);
2656 constr
->top
.SetDone(TRUE
);
2661 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2663 wxLayoutConstraints
*constr
= GetConstraints();
2666 *w
= constr
->width
.GetValue();
2667 *h
= constr
->height
.GetValue();
2673 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2675 wxLayoutConstraints
*constr
= GetConstraints();
2678 *w
= constr
->width
.GetValue();
2679 *h
= constr
->height
.GetValue();
2682 GetClientSize(w
, h
);
2685 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2687 wxLayoutConstraints
*constr
= GetConstraints();
2690 *x
= constr
->left
.GetValue();
2691 *y
= constr
->top
.GetValue();
2697 bool wxWindow::AcceptsFocus() const
2699 return IsEnabled() && IsShown();
2702 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )