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;
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_blockEventsOnDrag
) return TRUE
;
307 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
309 gtk_widget_grab_focus (win
->m_wxwindow
);
312 printf( "GrabFocus from " );
313 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
314 printf( win->GetClassInfo()->GetClassName() );
321 if (!win
->HasVMT()) return TRUE
;
324 printf( "OnButtonPress from " );
325 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
326 printf( win->GetClassInfo()->GetClassName() );
330 wxEventType event_type
= wxEVT_LEFT_DOWN
;
332 if (gdk_event
->button
== 1)
334 switch (gdk_event
->type
)
336 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
337 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
341 else if (gdk_event
->button
== 2)
343 switch (gdk_event
->type
)
345 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
346 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
350 else if (gdk_event
->button
== 3)
352 switch (gdk_event
->type
)
354 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
355 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
360 wxMouseEvent
event( event_type
);
361 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
362 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
363 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
364 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
365 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
366 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
367 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
369 event
.m_x
= (long)gdk_event
->x
;
370 event
.m_y
= (long)gdk_event
->y
;
372 // 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
;
395 event
.SetEventObject( win
);
397 if (win
->GetEventHandler()->ProcessEvent( event
))
398 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
403 //-----------------------------------------------------------------------------
404 // "button_release_event"
405 //-----------------------------------------------------------------------------
407 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
409 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
411 if (g_blockEventsOnDrag
) return TRUE
;
413 if (!win
->HasVMT()) return TRUE
;
416 printf( "OnButtonRelease from " );
417 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
418 printf( win->GetClassInfo()->GetClassName() );
422 wxEventType event_type
= wxEVT_NULL
;
424 switch (gdk_event
->button
)
426 case 1: event_type
= wxEVT_LEFT_UP
; break;
427 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
428 case 3: event_type
= wxEVT_RIGHT_UP
; break;
431 wxMouseEvent
event( event_type
);
432 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
433 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
434 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
435 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
436 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
437 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
438 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
439 event
.m_x
= (long)gdk_event
->x
;
440 event
.m_y
= (long)gdk_event
->y
;
442 // Some control don't have their own X window and thus cannot get
447 wxNode
*node
= win
->GetChildren()->First();
450 wxWindow
*child
= (wxWindow
*)node
->Data();
451 if ((child
->m_x
<= event
.m_x
) &&
452 (child
->m_y
<= event
.m_y
) &&
453 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
454 (child
->m_y
+child
->m_height
>= event
.m_y
))
457 event
.m_x
-= child
->m_x
;
458 event
.m_y
-= child
->m_y
;
465 event
.SetEventObject( win
);
467 if (win
->GetEventHandler()->ProcessEvent( event
))
468 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
473 //-----------------------------------------------------------------------------
474 // "motion_notify_event"
475 //-----------------------------------------------------------------------------
477 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
479 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) 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
509 wxNode
*node
= win
->GetChildren()->First();
512 wxWindow
*child
= (wxWindow
*)node
->Data();
513 if ((child
->m_x
<= event
.m_x
) &&
514 (child
->m_y
<= event
.m_y
) &&
515 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
516 (child
->m_y
+child
->m_height
>= event
.m_y
))
519 event
.m_x
-= child
->m_x
;
520 event
.m_y
-= child
->m_y
;
527 event
.SetEventObject( win
);
529 if (win
->GetEventHandler()->ProcessEvent( event
))
530 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
535 //-----------------------------------------------------------------------------
537 //-----------------------------------------------------------------------------
539 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
541 if (g_blockEventsOnDrag
) return TRUE
;
544 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
546 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
548 printf( "SetFocus flag from " );
549 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
550 printf( win->GetClassInfo()->GetClassName() );
556 if (!win
->HasVMT()) return TRUE
;
559 printf( "OnSetFocus from " );
560 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
561 printf( win->GetClassInfo()->GetClassName() );
563 printf( WXSTRINGCAST win->GetLabel() );
567 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
568 event
.SetEventObject( win
);
570 if (win
->GetEventHandler()->ProcessEvent( event
))
571 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
576 //-----------------------------------------------------------------------------
578 //-----------------------------------------------------------------------------
580 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
582 if (g_blockEventsOnDrag
) return TRUE
;
585 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
586 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
589 if (!win
->HasVMT()) return TRUE
;
592 printf( "OnKillFocus from " );
593 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
594 printf( win->GetClassInfo()->GetClassName() );
598 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
599 event
.SetEventObject( win
);
601 if (win
->GetEventHandler()->ProcessEvent( event
))
602 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
607 //-----------------------------------------------------------------------------
608 // "enter_notify_event"
609 //-----------------------------------------------------------------------------
611 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
613 if (widget
->window
!= gdk_event
->window
) return TRUE
;
615 if (g_blockEventsOnDrag
) return TRUE
;
617 if (!win
->HasVMT()) return TRUE
;
620 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
622 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
623 event
.SetEventObject( win
);
625 if (win
->GetEventHandler()->ProcessEvent( event
))
626 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
631 //-----------------------------------------------------------------------------
632 // "leave_notify_event"
633 //-----------------------------------------------------------------------------
635 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
637 if (widget
->window
!= gdk_event
->window
) return TRUE
;
639 if (g_blockEventsOnDrag
) return TRUE
;
641 if (!win
->HasVMT()) return TRUE
;
644 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
646 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
647 event
.SetEventObject( win
);
649 if (win
->GetEventHandler()->ProcessEvent( event
))
650 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
655 //-----------------------------------------------------------------------------
656 // "value_changed" from m_vAdjust
657 //-----------------------------------------------------------------------------
659 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
661 if (g_blockEventsOnDrag
) return;
664 printf( "OnVScroll from " );
665 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
666 printf( win->GetClassInfo()->GetClassName() );
670 if (!win
->HasVMT()) return;
672 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
673 if (fabs(diff
) < 0.2) return;
675 wxEventType command
= wxEVT_NULL
;
677 float line_step
= win
->m_vAdjust
->step_increment
;
678 float page_step
= win
->m_vAdjust
->page_increment
;
680 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
681 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
682 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
683 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
684 else command
= wxEVT_SCROLL_THUMBTRACK
;
686 int value
= (int)(win
->m_vAdjust
->value
+0.5);
688 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
689 event
.SetEventObject( win
);
690 win
->GetEventHandler()->ProcessEvent( event
);
693 //-----------------------------------------------------------------------------
694 // "value_changed" from m_hAdjust
695 //-----------------------------------------------------------------------------
697 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
699 if (g_blockEventsOnDrag
) return;
702 printf( "OnHScroll from " );
703 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
704 printf( win->GetClassInfo()->GetClassName() );
708 if (!win
->HasVMT()) return;
710 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
711 if (fabs(diff
) < 0.2) return;
713 wxEventType command
= wxEVT_NULL
;
715 float line_step
= win
->m_hAdjust
->step_increment
;
716 float page_step
= win
->m_hAdjust
->page_increment
;
718 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
719 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
720 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
721 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
722 else command
= wxEVT_SCROLL_THUMBTRACK
;
724 int value
= (int)(win
->m_hAdjust
->value
+0.5);
726 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
727 event
.SetEventObject( win
);
728 win
->GetEventHandler()->ProcessEvent( event
);
731 //-----------------------------------------------------------------------------
732 // "changed" from m_vAdjust
733 //-----------------------------------------------------------------------------
735 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
737 if (g_blockEventsOnDrag
) return;
740 printf( "OnVScroll change from " );
741 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
742 printf( win->GetClassInfo()->GetClassName() );
746 if (!win
->HasVMT()) return;
748 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
749 int value
= (int)(win
->m_vAdjust
->value
+0.5);
751 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
752 event
.SetEventObject( win
);
753 win
->GetEventHandler()->ProcessEvent( event
);
756 //-----------------------------------------------------------------------------
757 // "changed" from m_hAdjust
758 //-----------------------------------------------------------------------------
760 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
762 if (g_blockEventsOnDrag
) return;
765 printf( "OnHScroll change from " );
766 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
767 printf( win->GetClassInfo()->GetClassName() );
771 if (!win
->HasVMT()) return;
773 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
774 int value
= (int)(win
->m_hAdjust
->value
+0.5);
776 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
777 event
.SetEventObject( win
);
778 win
->GetEventHandler()->ProcessEvent( event
);
781 //-----------------------------------------------------------------------------
782 // "drop_data_available_event"
783 //-----------------------------------------------------------------------------
785 static void gtk_window_drop_callback( GtkWidget
*widget
, GdkEvent
*event
, wxWindow
*win
)
787 if (!win
->HasVMT()) return;
789 if (win
->GetDropTarget())
793 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
794 win
->GetDropTarget()->Drop( event
, x
, y
);
798 g_free (event->dropdataavailable.data);
799 g_free (event->dropdataavailable.data_type);
803 //-----------------------------------------------------------------------------
805 //-----------------------------------------------------------------------------
807 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
809 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
810 EVT_SIZE(wxWindow::OnSize
)
811 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
812 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
813 EVT_IDLE(wxWindow::OnIdle
)
818 m_widget
= (GtkWidget
*) NULL
;
819 m_wxwindow
= (GtkWidget
*) NULL
;
820 m_parent
= (wxWindow
*) NULL
;
821 m_children
.DeleteContents( FALSE
);
831 m_eventHandler
= this;
832 m_windowValidator
= (wxValidator
*) NULL
;
834 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
835 m_font
= *wxSWISS_FONT
;
837 m_windowName
= "noname";
838 m_constraints
= (wxLayoutConstraints
*) NULL
;
839 m_constraintsInvolvedIn
= (wxList
*) NULL
;
840 m_windowSizer
= (wxSizer
*) NULL
;
841 m_sizerParent
= (wxWindow
*) NULL
;
842 m_autoLayout
= FALSE
;
846 m_hasScrolling
= FALSE
;
847 m_hAdjust
= (GtkAdjustment
*) NULL
;
848 m_vAdjust
= (GtkAdjustment
*) NULL
;
849 m_oldHorizontalPos
= 0.0;
850 m_oldVerticalPos
= 0.0;
853 m_pDropTarget
= (wxDropTarget
*) NULL
;
855 m_hasOwnStyle
= FALSE
;
858 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
859 const wxPoint
&pos
, const wxSize
&size
,
860 long style
, const wxString
&name
)
866 m_cursor
= (wxCursor
*) NULL
;
868 PreCreation( parent
, id
, pos
, size
, style
, name
);
870 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
871 m_hasScrolling
= TRUE
;
873 GtkScrolledWindow
*s_window
;
874 s_window
= GTK_SCROLLED_WINDOW(m_widget
);
876 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
877 scroll_class
->scrollbar_spacing
= 0;
879 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
881 m_oldHorizontalPos
= 0.0;
882 m_oldVerticalPos
= 0.0;
884 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
885 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
887 gtk_signal_connect (GTK_OBJECT (m_hAdjust
), "value_changed",
888 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
889 gtk_signal_connect (GTK_OBJECT (m_vAdjust
), "value_changed",
890 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
892 gtk_signal_connect (GTK_OBJECT (m_hAdjust
), "changed",
893 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
894 gtk_signal_connect (GTK_OBJECT (m_vAdjust
), "changed",
895 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
897 GtkViewport
*viewport
;
898 viewport
= GTK_VIEWPORT(s_window
->viewport
);
900 if (m_windowStyle
& wxRAISED_BORDER
)
902 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
904 else if (m_windowStyle
& wxSUNKEN_BORDER
)
906 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
910 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
913 m_wxwindow
= gtk_myfixed_new();
915 if (m_wxwindow
) GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
917 if (m_windowStyle
& wxTAB_TRAVERSAL
== wxTAB_TRAVERSAL
)
918 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
920 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
922 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
924 // shut the viewport up
925 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
926 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
928 // I _really_ don't want scrollbars in the beginning
929 m_vAdjust
->lower
= 0.0;
930 m_vAdjust
->upper
= 1.0;
931 m_vAdjust
->value
= 0.0;
932 m_vAdjust
->step_increment
= 1.0;
933 m_vAdjust
->page_increment
= 1.0;
934 m_vAdjust
->page_size
= 5.0;
935 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
936 m_hAdjust
->lower
= 0.0;
937 m_hAdjust
->upper
= 1.0;
938 m_hAdjust
->value
= 0.0;
939 m_hAdjust
->step_increment
= 1.0;
940 m_hAdjust
->page_increment
= 1.0;
941 m_hAdjust
->page_size
= 5.0;
942 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
944 gtk_widget_show( m_wxwindow
);
953 wxWindow::~wxWindow(void)
957 if (m_pDropTarget
) delete m_pDropTarget
;
959 if (m_parent
) m_parent
->RemoveChild( this );
960 if (m_widget
) Show( FALSE
);
964 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
966 if (m_widget
) gtk_widget_destroy( m_widget
);
970 DeleteRelatedConstraints();
973 // This removes any dangling pointers to this window
974 // in other windows' constraintsInvolvedIn lists.
975 UnsetConstraints(m_constraints
);
976 delete m_constraints
;
977 m_constraints
= (wxLayoutConstraints
*) NULL
;
981 delete m_windowSizer
;
982 m_windowSizer
= (wxSizer
*) NULL
;
984 // If this is a child of a sizer, remove self from parent
985 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
987 // Just in case the window has been Closed, but
988 // we're then deleting immediately: don't leave
989 // dangling pointers.
990 wxPendingDelete
.DeleteObject(this);
992 // Just in case we've loaded a top-level window via
993 // wxWindow::LoadNativeDialog but we weren't a dialog
995 wxTopLevelWindows
.DeleteObject(this);
997 if (m_windowValidator
) delete m_windowValidator
;
1000 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1001 const wxPoint
&pos
, const wxSize
&size
,
1002 long style
, const wxString
&name
)
1004 if (m_needParent
&& (parent
== NULL
))
1005 wxFatalError( "Need complete parent.", name
);
1007 m_widget
= (GtkWidget
*) NULL
;
1010 m_children
.DeleteContents( FALSE
);
1014 if (m_width
== -1) m_width
= 20;
1016 if (m_height
== -1) m_height
= 20;
1022 m_eventHandler
= this;
1025 if (m_cursor
== NULL
)
1026 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1027 m_font
= *wxSWISS_FONT
;
1028 m_backgroundColour
= wxWHITE
;
1029 m_foregroundColour
= wxBLACK
;
1030 m_windowStyle
= style
;
1031 m_windowName
= name
;
1032 m_constraints
= (wxLayoutConstraints
*) NULL
;
1033 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1034 m_windowSizer
= (wxSizer
*) NULL
;
1035 m_sizerParent
= (wxWindow
*) NULL
;
1036 m_autoLayout
= FALSE
;
1037 m_pDropTarget
= (wxDropTarget
*) NULL
;
1039 m_windowValidator
= (wxValidator
*) NULL
;
1040 m_hasOwnStyle
= FALSE
;
1043 void wxWindow::PostCreation(void)
1045 if (m_parent
) m_parent
->AddChild( this );
1049 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1050 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1052 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1053 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1056 ConnectWidget( GetConnectWidget() );
1058 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1062 gtk_widget_realize( m_wxwindow
);
1063 gdk_gc_set_exposures( m_wxwindow
->style
->fg_gc
[0], TRUE
);
1066 SetCursor( wxSTANDARD_CURSOR
);
1071 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1073 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1074 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1076 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1077 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1079 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1080 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1082 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1083 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1085 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1086 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1088 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1089 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1091 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1092 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1094 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1095 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1098 bool wxWindow::HasVMT(void)
1103 bool wxWindow::Close( bool force
)
1105 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1106 event
.SetEventObject(this);
1107 event
.SetForce(force
);
1109 return GetEventHandler()->ProcessEvent(event
);
1112 bool wxWindow::Destroy(void)
1119 bool wxWindow::DestroyChildren(void)
1124 while ((node
= GetChildren()->First()) != (wxNode
*)NULL
)
1127 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1130 if (GetChildren()->Member(child
)) delete node
;
1137 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1139 // are we to set fonts here ?
1142 void wxWindow::ImplementSetSize(void)
1144 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1145 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1146 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_minWidth
;
1147 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_minHeight
;
1148 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1151 void wxWindow::ImplementSetPosition(void)
1153 if (IS_KIND_OF(this,wxFrame
) || IS_KIND_OF(this,wxDialog
))
1155 if ((m_x
!= -1) || (m_y
!= -1))
1156 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
1162 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1166 if ((m_parent
) && (m_parent
->m_wxwindow
))
1167 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
, m_y
);
1169 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1172 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1174 if (m_resizing
) return; // I don't like recursions
1182 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1184 if (newX
== -1) newX
= m_x
;
1185 if (newY
== -1) newY
= m_y
;
1186 if (newW
== -1) newW
= m_width
;
1187 if (newH
== -1) newH
= m_height
;
1190 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1192 if (newW
== -1) newW
= 80;
1195 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1197 if (newH
== -1) newH
= 26;
1200 if ((m_x
!= newX
) || (m_y
!= newY
) || (!m_sizeSet
))
1204 ImplementSetPosition();
1206 if ((m_width
!= newW
) || (m_height
!= newH
) || (!m_sizeSet
))
1214 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1215 event
.SetEventObject( this );
1216 ProcessEvent( event
);
1221 void wxWindow::SetSize( int width
, int height
)
1223 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1226 void wxWindow::Move( int x
, int y
)
1228 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1231 void wxWindow::GetSize( int *width
, int *height
) const
1233 if (width
) (*width
) = m_width
;
1234 if (height
) (*height
) = m_height
;
1237 void wxWindow::SetClientSize( int width
, int height
)
1241 SetSize( width
, height
);
1248 if (!m_hasScrolling
)
1251 do we have sunken dialogs ?
1253 GtkStyleClass *window_class = m_wxwindow->style->klass;
1255 dw += 2 * window_class->xthickness;
1256 dh += 2 * window_class->ythickness;
1261 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1262 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1264 GtkWidget
*viewport
= scroll_window
->viewport
;
1265 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1267 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1268 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1270 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1271 (m_windowStyle
& wxSUNKEN_BORDER
))
1273 dw
+= 2 * viewport_class
->xthickness
;
1274 dh
+= 2 * viewport_class
->ythickness
;
1277 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1279 dw
+= vscrollbar
->allocation
.width
;
1280 dw
+= scroll_class
->scrollbar_spacing
;
1283 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1285 dh
+= hscrollbar
->allocation
.height
;
1286 dw
+= scroll_class
->scrollbar_spacing
;
1290 SetSize( width
+dw
, height
+dh
);
1294 void wxWindow::GetClientSize( int *width
, int *height
) const
1298 if (width
) (*width
) = m_width
;
1299 if (height
) (*height
) = m_height
;
1306 if (!m_hasScrolling
)
1309 do we have sunken dialogs ?
1311 GtkStyleClass *window_class = m_wxwindow->style->klass;
1313 dw += 2 * window_class->xthickness;
1314 dh += 2 * window_class->ythickness;
1319 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1320 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1322 GtkWidget
*viewport
= scroll_window
->viewport
;
1323 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1325 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1326 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1328 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1329 (m_windowStyle
& wxSUNKEN_BORDER
))
1331 dw
+= 2 * viewport_class
->xthickness
;
1332 dh
+= 2 * viewport_class
->ythickness
;
1335 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1337 // dw += vscrollbar->allocation.width;
1338 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1339 dw
+= scroll_class
->scrollbar_spacing
;
1342 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1344 // dh += hscrollbar->allocation.height;
1346 dh
+= scroll_class
->scrollbar_spacing
;
1350 if (width
) (*width
) = m_width
- dw
;
1351 if (height
) (*height
) = m_height
- dh
;
1355 void wxWindow::GetPosition( int *x
, int *y
) const
1361 void wxWindow::ClientToScreen( int *x
, int *y
)
1363 GdkWindow
*source
= (GdkWindow
*) NULL
;
1365 source
= m_wxwindow
->window
;
1367 source
= m_widget
->window
;
1371 gdk_window_get_origin( source
, &org_x
, &org_y
);
1375 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1377 org_x
+= m_widget
->allocation
.x
;
1378 org_y
+= m_widget
->allocation
.y
;
1386 void wxWindow::ScreenToClient( int *x
, int *y
)
1388 GdkWindow
*source
= (GdkWindow
*) NULL
;
1390 source
= m_wxwindow
->window
;
1392 source
= m_widget
->window
;
1396 gdk_window_get_origin( source
, &org_x
, &org_y
);
1400 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1402 org_x
+= m_widget
->allocation
.x
;
1403 org_y
+= m_widget
->allocation
.y
;
1411 void wxWindow::Centre( int direction
)
1413 if (IS_KIND_OF(this,wxDialog
) || IS_KIND_OF(this,wxFrame
))
1415 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (gdk_screen_width () - m_width
) / 2;
1416 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (gdk_screen_height () - m_height
) / 2;
1417 ImplementSetPosition();
1425 m_parent
->GetSize( &p_w
, &p_h
);
1426 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (p_w
- m_width
) / 2;
1427 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (p_h
- m_height
) / 2;
1428 ImplementSetPosition();
1433 void wxWindow::Fit(void)
1437 wxNode
*node
= GetChildren()->First();
1440 wxWindow
*win
= (wxWindow
*)node
->Data();
1442 win
->GetPosition(&wx
, &wy
);
1443 win
->GetSize(&ww
, &wh
);
1444 if ( wx
+ ww
> maxX
)
1446 if ( wy
+ wh
> maxY
)
1449 node
= node
->Next();
1451 SetClientSize(maxX
+ 5, maxY
+ 10);
1454 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1462 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1464 //if (GetAutoLayout()) Layout();
1467 bool wxWindow::Show( bool show
)
1470 gtk_widget_show( m_widget
);
1472 gtk_widget_hide( m_widget
);
1477 void wxWindow::Enable( bool enable
)
1479 m_isEnabled
= enable
;
1480 gtk_widget_set_sensitive( m_widget
, enable
);
1481 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1484 int wxWindow::GetCharHeight(void) const
1486 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1487 return font
->ascent
+ font
->descent
;
1490 int wxWindow::GetCharWidth(void) const
1492 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1493 return gdk_string_width( font
, "H" );
1496 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1497 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1499 wxFont fontToUse
= m_font
;
1500 if (theFont
) fontToUse
= *theFont
;
1502 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1503 if (x
) (*x
) = gdk_string_width( font
, string
);
1504 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1505 if (descent
) (*descent
) = font
->descent
;
1506 if (externalLeading
) (*externalLeading
) = 0; // ??
1509 void wxWindow::MakeModal( bool modal
)
1512 // Disable all other windows
1513 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1515 wxNode
*node
= wxTopLevelWindows
.First();
1518 wxWindow
*win
= (wxWindow
*)node
->Data();
1520 win
->Enable(!modal
);
1522 node
= node
->Next();
1527 void wxWindow::SetFocus(void)
1529 GtkWidget
*connect_widget
= GetConnectWidget();
1532 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) && !GTK_WIDGET_HAS_FOCUS (connect_widget
) )
1534 gtk_widget_grab_focus (connect_widget
);
1539 bool wxWindow::OnClose(void)
1544 void wxWindow::AddChild( wxWindow
*child
)
1546 // Addchild is (often) called before the program
1547 // has left the parents constructor so that no
1548 // virtual tables work yet. The approach below
1549 // practically imitates virtual tables, i.e. it
1550 // implements a different AddChild() behaviour
1551 // for wxFrame, wxDialog, wxWindow and
1552 // wxMDIParentFrame.
1554 // wxFrame and wxDialog as children aren't placed into the parents
1556 if (( IS_KIND_OF(child
,wxFrame
) || IS_KIND_OF(child
,wxDialog
) ) &&
1557 (!IS_KIND_OF(child
,wxMDIChildFrame
)))
1559 m_children
.Append( child
);
1561 if ((child
->m_x
!= -1) && (child
->m_y
!= -1))
1562 gtk_widget_set_uposition( child
->m_widget
, child
->m_x
, child
->m_y
);
1567 // In the case of an wxMDIChildFrame descendant, we use the
1568 // client windows's AddChild()
1570 if (IS_KIND_OF(this,wxMDIParentFrame
))
1572 if (IS_KIND_OF(child
,wxMDIChildFrame
))
1574 wxMDIClientWindow
*client
= ((wxMDIParentFrame
*)this)->GetClientWindow();
1577 client
->AddChild( child
);
1583 // wxNotebook is very special, so it has a private AddChild()
1585 if (IS_KIND_OF(this,wxNotebook
))
1587 wxNotebook
*tab
= (wxNotebook
*)this;
1588 tab
->AddChild( child
);
1592 // wxFrame has a private AddChild
1594 if (IS_KIND_OF(this,wxFrame
) && !IS_KIND_OF(this,wxMDIChildFrame
))
1596 wxFrame
*frame
= (wxFrame
*)this;
1597 frame
->AddChild( child
);
1603 m_children
.Append( child
);
1604 if (m_wxwindow
) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), child
->m_widget
,
1605 child
->m_x
, child
->m_y
);
1607 gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height
);
1610 wxList
*wxWindow::GetChildren(void)
1612 return (&m_children
);
1615 void wxWindow::RemoveChild( wxWindow
*child
)
1618 GetChildren()->DeleteObject( child
);
1619 child
->m_parent
= (wxWindow
*) NULL
;
1622 void wxWindow::SetReturnCode( int retCode
)
1624 m_retCode
= retCode
;
1627 int wxWindow::GetReturnCode(void)
1632 void wxWindow::Raise(void)
1634 if (m_widget
) gdk_window_raise( m_widget
->window
);
1637 void wxWindow::Lower(void)
1639 if (m_widget
) gdk_window_lower( m_widget
->window
);
1642 wxEvtHandler
*wxWindow::GetEventHandler(void)
1644 return m_eventHandler
;
1647 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
1649 m_eventHandler
= handler
;
1652 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
1654 handler
->SetNextHandler(GetEventHandler());
1655 SetEventHandler(handler
);
1658 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
1660 if ( GetEventHandler() )
1662 wxEvtHandler
*handlerA
= GetEventHandler();
1663 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
1664 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
1665 SetEventHandler(handlerB
);
1666 if ( deleteHandler
)
1669 return (wxEvtHandler
*) NULL
;
1675 return (wxEvtHandler
*) NULL
;
1678 wxValidator
*wxWindow::GetValidator(void)
1680 return m_windowValidator
;
1683 void wxWindow::SetValidator( const wxValidator
& validator
)
1685 if (m_windowValidator
) delete m_windowValidator
;
1686 m_windowValidator
= validator
.Clone();
1687 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
1690 bool wxWindow::IsBeingDeleted(void)
1695 void wxWindow::SetId( wxWindowID id
)
1700 wxWindowID
wxWindow::GetId(void)
1705 void wxWindow::SetCursor( const wxCursor
&cursor
)
1707 wxASSERT(m_cursor
!= NULL
);
1709 if (m_cursor
!= NULL
)
1710 if (*m_cursor
== cursor
)
1712 (*m_cursor
) = cursor
;
1713 if (m_widget
->window
)
1714 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
1715 if (m_wxwindow
&& m_wxwindow
->window
)
1716 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
1719 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
1721 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
1724 gdk_window_clear_area( m_wxwindow
->window
,
1738 GetClientSize( &w
, &h
);
1740 GdkRectangle gdk_rect
;
1744 gdk_rect
.height
= h
;
1745 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1750 GdkRectangle gdk_rect
;
1751 gdk_rect
.x
= rect
->x
;
1752 gdk_rect
.y
= rect
->y
;
1753 gdk_rect
.width
= rect
->width
;
1754 gdk_rect
.height
= rect
->height
;
1757 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1759 gtk_widget_draw( m_widget
, &gdk_rect
);
1763 wxRegion
wxWindow::GetUpdateRegion() const
1765 return m_updateRegion
;
1768 bool wxWindow::IsExposed( int x
, int y
) const
1770 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
1773 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
1775 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
1778 bool wxWindow::IsExposed( const wxPoint
& pt
) const
1780 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
1783 bool wxWindow::IsExposed( const wxRect
& rect
) const
1785 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
1788 void wxWindow::Clear(void)
1790 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
1793 wxColour
wxWindow::GetBackgroundColour(void) const
1795 return m_backgroundColour
;
1798 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
1800 m_backgroundColour
= colour
;
1803 m_backgroundColour
.CalcPixel( m_wxwindow
->style
->colormap
);
1804 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
1805 gdk_window_clear( m_wxwindow
->window
);
1810 wxColour
wxWindow::GetForegroundColour(void) const
1812 return m_foregroundColour
;
1815 void wxWindow::SetForegroundColour( const wxColour
&colour
)
1817 m_foregroundColour
= colour
;
1820 bool wxWindow::Validate(void)
1822 wxNode
*node
= GetChildren()->First();
1825 wxWindow
*child
= (wxWindow
*)node
->Data();
1826 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
1828 node
= node
->Next();
1833 bool wxWindow::TransferDataToWindow(void)
1835 wxNode
*node
= GetChildren()->First();
1838 wxWindow
*child
= (wxWindow
*)node
->Data();
1839 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
1840 !child
->GetValidator()->TransferToWindow() )
1842 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
1845 node
= node
->Next();
1850 bool wxWindow::TransferDataFromWindow(void)
1852 wxNode
*node
= GetChildren()->First();
1855 wxWindow
*child
= (wxWindow
*)node
->Data();
1856 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
1858 node
= node
->Next();
1863 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
1865 m_acceleratorTable
= accel
;
1868 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
1870 TransferDataToWindow();
1873 void wxWindow::InitDialog(void)
1875 wxInitDialogEvent
event(GetId());
1876 event
.SetEventObject( this );
1877 GetEventHandler()->ProcessEvent(event
);
1880 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
1882 menu
->SetInvokingWindow( win
);
1883 wxNode
*node
= menu
->m_items
.First();
1886 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
1887 if (menuitem
->IsSubMenu())
1888 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
1889 node
= node
->Next();
1893 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
1895 SetInvokingWindow( menu
, this );
1896 gtk_menu_popup( GTK_MENU(menu
->m_menu
), (GtkWidget
*) NULL
, (GtkWidget
*) NULL
, (GtkMenuPositionFunc
) NULL
, NULL
, 0, 0 );
1900 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
1902 GtkWidget
*dnd_widget
= GetConnectWidget();
1904 DisconnectDnDWidget( dnd_widget
);
1906 if (m_pDropTarget
) delete m_pDropTarget
;
1907 m_pDropTarget
= dropTarget
;
1909 ConnectDnDWidget( dnd_widget
);
1912 wxDropTarget
*wxWindow::GetDropTarget() const
1914 return m_pDropTarget
;
1917 void wxWindow::ConnectDnDWidget( GtkWidget
*widget
)
1919 if (!m_pDropTarget
) return;
1921 m_pDropTarget
->RegisterWidget( widget
);
1923 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
1924 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
1927 void wxWindow::DisconnectDnDWidget( GtkWidget
*widget
)
1929 if (!m_pDropTarget
) return;
1931 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
1932 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
1934 m_pDropTarget
->UnregisterWidget( widget
);
1937 GtkWidget
* wxWindow::GetConnectWidget(void)
1939 GtkWidget
*connect_widget
= m_widget
;
1940 if (m_wxwindow
) connect_widget
= m_wxwindow
;
1942 return connect_widget
;
1945 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
1947 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
1948 return (window
== m_widget
->window
);
1951 void wxWindow::SetFont( const wxFont
&font
)
1953 if (((wxFont
*)&font
)->Ok())
1956 m_font
= *wxSWISS_FONT
;
1958 GtkStyle
*style
= (GtkStyle
*) NULL
;
1961 m_hasOwnStyle
= TRUE
;
1962 style
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
1966 style
= gtk_widget_get_style( m_widget
);
1969 gdk_font_unref( style
->font
);
1970 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
1972 gtk_widget_set_style( m_widget
, style
);
1975 wxFont
*wxWindow::GetFont(void)
1980 void wxWindow::SetWindowStyleFlag( long flag
)
1982 m_windowStyle
= flag
;
1985 long wxWindow::GetWindowStyleFlag(void) const
1987 return m_windowStyle
;
1990 void wxWindow::CaptureMouse(void)
1992 GtkWidget
*connect_widget
= GetConnectWidget();
1993 gtk_grab_add( connect_widget
);
1994 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
1996 (GDK_BUTTON_PRESS_MASK
|
1997 GDK_BUTTON_RELEASE_MASK
|
1998 GDK_POINTER_MOTION_MASK
),
1999 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
2003 void wxWindow::ReleaseMouse(void)
2005 GtkWidget
*connect_widget
= GetConnectWidget();
2006 gtk_grab_remove( connect_widget
);
2007 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2008 g_capturing
= FALSE
;
2011 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2015 wxString
wxWindow::GetTitle(void) const
2017 return (wxString
&)m_windowName
;
2020 wxString
wxWindow::GetLabel(void) const
2025 void wxWindow::SetName( const wxString
&name
)
2027 m_windowName
= name
;
2030 wxString
wxWindow::GetName(void) const
2032 return (wxString
&)m_windowName
;
2035 bool wxWindow::IsShown(void) const
2040 bool wxWindow::IsRetained(void)
2045 wxWindow
*wxWindow::FindWindow( long id
)
2047 if (id
== m_windowId
) return this;
2048 wxNode
*node
= m_children
.First();
2051 wxWindow
*child
= (wxWindow
*)node
->Data();
2052 wxWindow
*res
= child
->FindWindow( id
);
2053 if (res
) return res
;
2054 node
= node
->Next();
2056 return (wxWindow
*) NULL
;
2059 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2061 if (name
== m_windowName
) return this;
2062 wxNode
*node
= m_children
.First();
2065 wxWindow
*child
= (wxWindow
*)node
->Data();
2066 wxWindow
*res
= child
->FindWindow( name
);
2067 if (res
) return res
;
2068 node
= node
->Next();
2070 return (wxWindow
*) NULL
;
2073 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2074 int range
, bool WXUNUSED(refresh
) )
2076 if (!m_wxwindow
) return;
2078 if (orient
== wxHORIZONTAL
)
2080 float fpos
= (float)pos
;
2081 m_oldHorizontalPos
= fpos
;
2082 float frange
= (float)range
;
2083 float fthumb
= (float)thumbVisible
;
2085 if ((fabs(fpos
-m_hAdjust
->value
) < 0.2) &&
2086 (fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2087 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2090 m_hAdjust
->lower
= 0.0;
2091 m_hAdjust
->upper
= frange
;
2092 m_hAdjust
->value
= fpos
;
2093 m_hAdjust
->step_increment
= 1.0;
2094 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2095 m_hAdjust
->page_size
= fthumb
;
2099 float fpos
= (float)pos
;
2100 m_oldVerticalPos
= fpos
;
2101 float frange
= (float)range
;
2102 float fthumb
= (float)thumbVisible
;
2104 if ((fabs(fpos
-m_vAdjust
->value
) < 0.2) &&
2105 (fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2106 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2109 m_vAdjust
->lower
= 0.0;
2110 m_vAdjust
->upper
= frange
;
2111 m_vAdjust
->value
= fpos
;
2112 m_vAdjust
->step_increment
= 1.0;
2113 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2114 m_vAdjust
->page_size
= fthumb
;
2117 if (m_wxwindow
->window
)
2119 if (orient
== wxHORIZONTAL
)
2120 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2122 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2124 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2128 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2130 if (!m_wxwindow
) return;
2132 if (orient
== wxHORIZONTAL
)
2134 float fpos
= (float)pos
;
2135 m_oldHorizontalPos
= fpos
;
2137 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2138 m_hAdjust
->value
= fpos
;
2142 float fpos
= (float)pos
;
2143 m_oldVerticalPos
= fpos
;
2144 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2145 m_vAdjust
->value
= fpos
;
2148 if (m_wxwindow
->window
)
2150 if (orient
== wxHORIZONTAL
)
2151 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2153 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2157 int wxWindow::GetScrollThumb( int orient
) const
2159 if (!m_wxwindow
) return 0;
2161 if (orient
== wxHORIZONTAL
)
2162 return (int)(m_hAdjust
->page_size
+0.5);
2164 return (int)(m_vAdjust
->page_size
+0.5);
2167 int wxWindow::GetScrollPos( int orient
) const
2169 if (!m_wxwindow
) return 0;
2171 if (orient
== wxHORIZONTAL
)
2172 return (int)(m_hAdjust
->value
+0.5);
2174 return (int)(m_vAdjust
->value
+0.5);
2177 int wxWindow::GetScrollRange( int orient
) const
2179 if (!m_wxwindow
) return 0;
2181 if (orient
== wxHORIZONTAL
)
2182 return (int)(m_hAdjust
->upper
+0.5);
2184 return (int)(m_vAdjust
->upper
+0.5);
2187 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2189 if (!m_wxwindow
) return;
2192 bool refresh = FALSE;
2194 if ((m_drawingOffsetX == 0) && (m_drawingOffsetY == 0))
2196 m_drawingOffsetX = -16000;
2197 m_drawingOffsetY = -16000;
2202 m_drawingOffsetX += dx;
2203 m_drawingOffsetY += dy;
2206 // printf( "X: %d Y: %d \n", (int)m_drawingOffsetX, (int)m_drawingOffsetY );
2208 gtk_myfixed_set_offset( GTK_MYFIXED(m_wxwindow), m_drawingOffsetX, m_drawingOffsetY );
2210 if (refresh) Refresh();
2212 The code here is very nifty, but it doesn't work with
2213 overlapping windows...
2218 GetClientSize( &cw
, &ch
);
2220 int w
= cw
- abs(dx
);
2221 int h
= ch
- abs(dy
);
2222 if ((h
< 0) || (w
< 0))
2229 if (dx
< 0) s_x
= -dx
;
2230 if (dy
< 0) s_y
= -dy
;
2233 if (dx
> 0) d_x
= dx
;
2234 if (dy
> 0) d_y
= dy
;
2235 gdk_window_copy_area( m_wxwindow
->window
, m_wxwindow
->style
->fg_gc
[0], d_x
, d_y
,
2236 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2239 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2240 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2241 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2242 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2244 Refresh( TRUE
, &rect
);
2247 //-------------------------------------------------------------------------------------
2249 //-------------------------------------------------------------------------------------
2251 wxLayoutConstraints
*wxWindow::GetConstraints(void) const
2253 return m_constraints
;
2256 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2260 UnsetConstraints(m_constraints
);
2261 delete m_constraints
;
2263 m_constraints
= constraints
;
2266 // Make sure other windows know they're part of a 'meaningful relationship'
2267 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2268 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2269 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2270 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2271 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2272 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2273 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2274 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2275 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2276 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2277 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2278 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2279 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2280 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2281 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2282 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2288 void wxWindow::SetAutoLayout( bool autoLayout
)
2290 m_autoLayout
= autoLayout
;
2293 bool wxWindow::GetAutoLayout(void) const
2295 return m_autoLayout
;
2298 wxSizer
*wxWindow::GetSizer(void) const
2300 return m_windowSizer
;
2303 void wxWindow::SetSizerParent( wxWindow
*win
)
2305 m_sizerParent
= win
;
2308 wxWindow
*wxWindow::GetSizerParent(void) const
2310 return m_sizerParent
;
2313 // This removes any dangling pointers to this window
2314 // in other windows' constraintsInvolvedIn lists.
2315 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2319 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2320 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2321 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2322 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2323 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2324 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2325 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2326 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2327 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2328 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2329 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2330 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2331 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2332 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2333 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2334 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2338 // Back-pointer to other windows we're involved with, so if we delete
2339 // this window, we must delete any constraints we're involved with.
2340 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2342 if (!m_constraintsInvolvedIn
)
2343 m_constraintsInvolvedIn
= new wxList
;
2344 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2345 m_constraintsInvolvedIn
->Append(otherWin
);
2348 // REMOVE back-pointer to other windows we're involved with.
2349 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2351 if (m_constraintsInvolvedIn
)
2352 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2355 // Reset any constraints that mention this window
2356 void wxWindow::DeleteRelatedConstraints(void)
2358 if (m_constraintsInvolvedIn
)
2360 wxNode
*node
= m_constraintsInvolvedIn
->First();
2363 wxWindow
*win
= (wxWindow
*)node
->Data();
2364 wxNode
*next
= node
->Next();
2365 wxLayoutConstraints
*constr
= win
->GetConstraints();
2367 // Reset any constraints involving this window
2370 constr
->left
.ResetIfWin((wxWindow
*)this);
2371 constr
->top
.ResetIfWin((wxWindow
*)this);
2372 constr
->right
.ResetIfWin((wxWindow
*)this);
2373 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2374 constr
->width
.ResetIfWin((wxWindow
*)this);
2375 constr
->height
.ResetIfWin((wxWindow
*)this);
2376 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2377 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2382 delete m_constraintsInvolvedIn
;
2383 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2387 void wxWindow::SetSizer(wxSizer
*sizer
)
2389 m_windowSizer
= sizer
;
2391 sizer
->SetSizerParent((wxWindow
*)this);
2398 bool wxWindow::Layout(void)
2400 if (GetConstraints())
2403 GetClientSize(&w
, &h
);
2404 GetConstraints()->width
.SetValue(w
);
2405 GetConstraints()->height
.SetValue(h
);
2408 // If top level (one sizer), evaluate the sizer's constraints.
2412 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2413 GetSizer()->LayoutPhase1(&noChanges
);
2414 GetSizer()->LayoutPhase2(&noChanges
);
2415 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2420 // Otherwise, evaluate child constraints
2421 ResetConstraints(); // Mark all constraints as unevaluated
2422 DoPhase(1); // Just one phase need if no sizers involved
2424 SetConstraintSizes(); // Recursively set the real window sizes
2430 // Do a phase of evaluating constraints:
2431 // the default behaviour. wxSizers may do a similar
2432 // thing, but also impose their own 'constraints'
2433 // and order the evaluation differently.
2434 bool wxWindow::LayoutPhase1(int *noChanges
)
2436 wxLayoutConstraints
*constr
= GetConstraints();
2439 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2445 bool wxWindow::LayoutPhase2(int *noChanges
)
2455 // Do a phase of evaluating child constraints
2456 bool wxWindow::DoPhase(int phase
)
2458 int noIterations
= 0;
2459 int maxIterations
= 500;
2463 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2467 wxNode
*node
= GetChildren()->First();
2470 wxWindow
*child
= (wxWindow
*)node
->Data();
2471 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2473 wxLayoutConstraints
*constr
= child
->GetConstraints();
2476 if (succeeded
.Member(child
))
2481 int tempNoChanges
= 0;
2482 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2483 noChanges
+= tempNoChanges
;
2486 succeeded
.Append(child
);
2491 node
= node
->Next();
2498 void wxWindow::ResetConstraints(void)
2500 wxLayoutConstraints
*constr
= GetConstraints();
2503 constr
->left
.SetDone(FALSE
);
2504 constr
->top
.SetDone(FALSE
);
2505 constr
->right
.SetDone(FALSE
);
2506 constr
->bottom
.SetDone(FALSE
);
2507 constr
->width
.SetDone(FALSE
);
2508 constr
->height
.SetDone(FALSE
);
2509 constr
->centreX
.SetDone(FALSE
);
2510 constr
->centreY
.SetDone(FALSE
);
2512 wxNode
*node
= GetChildren()->First();
2515 wxWindow
*win
= (wxWindow
*)node
->Data();
2516 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2517 win
->ResetConstraints();
2518 node
= node
->Next();
2522 // Need to distinguish between setting the 'fake' size for
2523 // windows and sizers, and setting the real values.
2524 void wxWindow::SetConstraintSizes(bool recurse
)
2526 wxLayoutConstraints
*constr
= GetConstraints();
2527 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2528 constr
->width
.GetDone() && constr
->height
.GetDone())
2530 int x
= constr
->left
.GetValue();
2531 int y
= constr
->top
.GetValue();
2532 int w
= constr
->width
.GetValue();
2533 int h
= constr
->height
.GetValue();
2535 // If we don't want to resize this window, just move it...
2536 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2537 (constr
->height
.GetRelationship() != wxAsIs
))
2539 // Calls Layout() recursively. AAAGH. How can we stop that.
2540 // Simply take Layout() out of non-top level OnSizes.
2541 SizerSetSize(x
, y
, w
, h
);
2550 char *windowClass
= this->GetClassInfo()->GetClassName();
2553 if (GetName() == "")
2554 winName
= _("unnamed");
2556 winName
= GetName();
2557 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2558 if (!constr
->left
.GetDone())
2559 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2560 if (!constr
->right
.GetDone())
2561 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2562 if (!constr
->width
.GetDone())
2563 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2564 if (!constr
->height
.GetDone())
2565 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2566 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2571 wxNode
*node
= GetChildren()->First();
2574 wxWindow
*win
= (wxWindow
*)node
->Data();
2575 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2576 win
->SetConstraintSizes();
2577 node
= node
->Next();
2582 // This assumes that all sizers are 'on' the same
2583 // window, i.e. the parent of this window.
2584 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2586 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2587 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2591 m_sizerParent
->GetPosition(&xp
, &yp
);
2592 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2597 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2601 TransformSizerToActual(&xx
, &yy
);
2602 SetSize(xx
, yy
, w
, h
);
2605 void wxWindow::SizerMove(int x
, int y
)
2609 TransformSizerToActual(&xx
, &yy
);
2613 // Only set the size/position of the constraint (if any)
2614 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2616 wxLayoutConstraints
*constr
= GetConstraints();
2621 constr
->left
.SetValue(x
);
2622 constr
->left
.SetDone(TRUE
);
2626 constr
->top
.SetValue(y
);
2627 constr
->top
.SetDone(TRUE
);
2631 constr
->width
.SetValue(w
);
2632 constr
->width
.SetDone(TRUE
);
2636 constr
->height
.SetValue(h
);
2637 constr
->height
.SetDone(TRUE
);
2642 void wxWindow::MoveConstraint(int x
, int y
)
2644 wxLayoutConstraints
*constr
= GetConstraints();
2649 constr
->left
.SetValue(x
);
2650 constr
->left
.SetDone(TRUE
);
2654 constr
->top
.SetValue(y
);
2655 constr
->top
.SetDone(TRUE
);
2660 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2662 wxLayoutConstraints
*constr
= GetConstraints();
2665 *w
= constr
->width
.GetValue();
2666 *h
= constr
->height
.GetValue();
2672 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2674 wxLayoutConstraints
*constr
= GetConstraints();
2677 *w
= constr
->width
.GetValue();
2678 *h
= constr
->height
.GetValue();
2681 GetClientSize(w
, h
);
2684 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2686 wxLayoutConstraints
*constr
= GetConstraints();
2689 *x
= constr
->left
.GetValue();
2690 *y
= constr
->top
.GetValue();
2696 bool wxWindow::AcceptsFocus() const
2698 return IsEnabled() && IsShown();
2701 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )