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
;
120 //-----------------------------------------------------------------------------
121 // "expose_event" (of m_wxwindow, not of m_widget)
122 //-----------------------------------------------------------------------------
124 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
126 if (!win
->HasVMT()) return;
127 if (g_blockEventsOnDrag
) return;
129 win
->m_updateRegion
.Union( gdk_event
->area
.x
,
131 gdk_event
->area
.width
,
132 gdk_event
->area
.height
);
134 if (gdk_event
->count
> 0) return;
136 wxPaintEvent
event( win
->GetId() );
137 event
.SetEventObject( win
);
138 win
->GetEventHandler()->ProcessEvent( event
);
140 win
->m_updateRegion
.Clear();
143 //-----------------------------------------------------------------------------
144 // "draw" (of m_wxwindow, not of m_widget)
145 //-----------------------------------------------------------------------------
147 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
149 if (!win
->HasVMT()) return;
150 if (g_blockEventsOnDrag
) return;
152 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
154 wxPaintEvent
event( win
->GetId() );
155 event
.SetEventObject( win
);
156 win
->GetEventHandler()->ProcessEvent( event
);
158 win
->m_updateRegion
.Clear();
161 //-----------------------------------------------------------------------------
163 //-----------------------------------------------------------------------------
165 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
167 if (!win
->HasVMT()) return FALSE
;
168 if (g_blockEventsOnDrag
) return FALSE
;
171 printf( "OnKeyPress from " );
172 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
173 printf( win->GetClassInfo()->GetClassName() );
178 switch (gdk_event
->keyval
)
180 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
181 case GDK_Tab
: key_code
= WXK_TAB
; break;
182 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
183 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
184 case GDK_Return
: key_code
= WXK_RETURN
; break;
185 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
186 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
187 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
188 case GDK_Delete
: key_code
= WXK_DELETE
; break;
189 case GDK_Home
: key_code
= WXK_HOME
; break;
190 case GDK_Left
: key_code
= WXK_LEFT
; break;
191 case GDK_Up
: key_code
= WXK_UP
; break;
192 case GDK_Right
: key_code
= WXK_RIGHT
; break;
193 case GDK_Down
: key_code
= WXK_DOWN
; break;
194 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
195 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
196 case GDK_Next
: key_code
= WXK_NEXT
; break;
197 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
198 case GDK_End
: key_code
= WXK_END
; break;
199 case GDK_Begin
: key_code
= WXK_HOME
; break;
200 case GDK_Select
: key_code
= WXK_SELECT
; break;
201 case GDK_Print
: key_code
= WXK_PRINT
; break;
202 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
203 case GDK_Insert
: key_code
= WXK_INSERT
; break;
204 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
205 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
206 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
207 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
208 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
209 case GDK_KP_Up
: key_code
= WXK_UP
; break;
210 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
211 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
212 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
213 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
214 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
215 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
216 case GDK_KP_End
: key_code
= WXK_END
; break;
217 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
218 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
219 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
220 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
221 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
222 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
223 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
224 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
225 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
226 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
227 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
228 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
229 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
230 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
231 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
232 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
233 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
234 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
235 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
236 case GDK_F1
: key_code
= WXK_F1
; break;
237 case GDK_F2
: key_code
= WXK_F2
; break;
238 case GDK_F3
: key_code
= WXK_F3
; break;
239 case GDK_F4
: key_code
= WXK_F4
; break;
240 case GDK_F5
: key_code
= WXK_F5
; break;
241 case GDK_F6
: key_code
= WXK_F6
; break;
242 case GDK_F7
: key_code
= WXK_F7
; break;
243 case GDK_F8
: key_code
= WXK_F8
; break;
244 case GDK_F9
: key_code
= WXK_F9
; break;
245 case GDK_F10
: key_code
= WXK_F10
; break;
246 case GDK_F11
: key_code
= WXK_F11
; break;
247 case GDK_F12
: key_code
= WXK_F12
; break;
250 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
251 key_code
= gdk_event
->keyval
;
255 if (!key_code
) return FALSE
;
257 wxKeyEvent
event( wxEVT_CHAR
);
258 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
259 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
260 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
261 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
262 event
.m_keyCode
= key_code
;
265 event
.SetEventObject( win
);
267 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
271 wxWindow
*ancestor
= win
;
274 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
277 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
278 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
281 ancestor
= ancestor
->GetParent();
287 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
288 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
294 //-----------------------------------------------------------------------------
295 // "button_press_event"
296 //-----------------------------------------------------------------------------
298 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
300 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
302 if (g_blockEventsOnDrag
) return TRUE
;
306 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
308 gtk_widget_grab_focus (win
->m_wxwindow
);
311 printf( "GrabFocus from " );
312 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
313 printf( win->GetClassInfo()->GetClassName() );
320 if (!win
->HasVMT()) return TRUE
;
323 printf( "OnButtonPress from " );
324 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
325 printf( win->GetClassInfo()->GetClassName() );
329 wxEventType event_type
= wxEVT_LEFT_DOWN
;
331 if (gdk_event
->button
== 1)
333 switch (gdk_event
->type
)
335 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
336 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
340 else if (gdk_event
->button
== 2)
342 switch (gdk_event
->type
)
344 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
345 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
349 else if (gdk_event
->button
== 3)
351 switch (gdk_event
->type
)
353 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
354 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
359 wxMouseEvent
event( event_type
);
360 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
361 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
362 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
363 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
364 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
365 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
366 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
368 event
.m_x
= (long)gdk_event
->x
;
369 event
.m_y
= (long)gdk_event
->y
;
371 // Some control don't have their own X window and thus cannot get
374 wxNode
*node
= win
->GetChildren()->First();
377 wxWindow
*child
= (wxWindow
*)node
->Data();
378 if ((child
->m_x
<= event
.m_x
) &&
379 (child
->m_y
<= event
.m_y
) &&
380 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
381 (child
->m_y
+child
->m_height
>= event
.m_y
))
384 event
.m_x
-= child
->m_x
;
385 event
.m_y
-= child
->m_y
;
391 event
.SetEventObject( win
);
393 if (win
->GetEventHandler()->ProcessEvent( event
))
394 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
399 //-----------------------------------------------------------------------------
400 // "button_release_event"
401 //-----------------------------------------------------------------------------
403 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
405 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
406 if (g_blockEventsOnDrag
) return TRUE
;
408 if (!win
->HasVMT()) return TRUE
;
411 printf( "OnButtonRelease from " );
412 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
413 printf( win->GetClassInfo()->GetClassName() );
417 wxEventType event_type
= wxEVT_NULL
;
419 switch (gdk_event
->button
)
421 case 1: event_type
= wxEVT_LEFT_UP
; break;
422 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
423 case 3: event_type
= wxEVT_RIGHT_UP
; break;
426 wxMouseEvent
event( event_type
);
427 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
428 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
429 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
430 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
431 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
432 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
433 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
434 event
.m_x
= (long)gdk_event
->x
;
435 event
.m_y
= (long)gdk_event
->y
;
437 // Some control don't have their own X window and thus cannot get
440 wxNode
*node
= win
->GetChildren()->First();
443 wxWindow
*child
= (wxWindow
*)node
->Data();
444 if ((child
->m_x
<= event
.m_x
) &&
445 (child
->m_y
<= event
.m_y
) &&
446 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
447 (child
->m_y
+child
->m_height
>= event
.m_y
))
450 event
.m_x
-= child
->m_x
;
451 event
.m_y
-= child
->m_y
;
457 event
.SetEventObject( win
);
459 if (win
->GetEventHandler()->ProcessEvent( event
))
460 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
465 //-----------------------------------------------------------------------------
466 // "motion_notify_event"
467 //-----------------------------------------------------------------------------
469 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
471 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
472 if (g_blockEventsOnDrag
) return TRUE
;
474 if (!win
->HasVMT()) return TRUE
;
477 printf( "OnMotion from " );
478 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
479 printf( win->GetClassInfo()->GetClassName() );
483 wxMouseEvent
event( wxEVT_MOTION
);
484 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
485 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
486 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
487 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
488 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
489 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
490 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
492 event
.m_x
= (long)gdk_event
->x
;
493 event
.m_y
= (long)gdk_event
->y
;
495 // Some control don't have their own X window and thus cannot get
498 wxNode
*node
= win
->GetChildren()->First();
501 wxWindow
*child
= (wxWindow
*)node
->Data();
502 if ((child
->m_x
<= event
.m_x
) &&
503 (child
->m_y
<= event
.m_y
) &&
504 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
505 (child
->m_y
+child
->m_height
>= event
.m_y
))
508 event
.m_x
-= child
->m_x
;
509 event
.m_y
-= child
->m_y
;
515 event
.SetEventObject( win
);
517 if (win
->GetEventHandler()->ProcessEvent( event
))
518 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
523 //-----------------------------------------------------------------------------
525 //-----------------------------------------------------------------------------
527 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
529 if (g_blockEventsOnDrag
) return TRUE
;
532 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
534 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
536 printf( "SetFocus flag from " );
537 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
538 printf( win->GetClassInfo()->GetClassName() );
544 if (!win
->HasVMT()) return TRUE
;
547 printf( "OnSetFocus from " );
548 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
549 printf( win->GetClassInfo()->GetClassName() );
551 printf( WXSTRINGCAST win->GetLabel() );
555 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
556 event
.SetEventObject( win
);
558 if (win
->GetEventHandler()->ProcessEvent( event
))
559 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
564 //-----------------------------------------------------------------------------
566 //-----------------------------------------------------------------------------
568 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
570 if (g_blockEventsOnDrag
) return TRUE
;
573 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
574 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
577 if (!win
->HasVMT()) return TRUE
;
580 printf( "OnKillFocus from " );
581 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
582 printf( win->GetClassInfo()->GetClassName() );
586 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
587 event
.SetEventObject( win
);
589 if (win
->GetEventHandler()->ProcessEvent( event
))
590 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
595 //-----------------------------------------------------------------------------
596 // "enter_notify_event"
597 //-----------------------------------------------------------------------------
599 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
601 if (widget
->window
!= gdk_event
->window
) return TRUE
;
602 if (g_blockEventsOnDrag
) return TRUE
;
603 if (!win
->HasVMT()) return TRUE
;
606 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
608 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
609 event
.SetEventObject( win
);
611 if (win
->GetEventHandler()->ProcessEvent( event
))
612 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
617 //-----------------------------------------------------------------------------
618 // "leave_notify_event"
619 //-----------------------------------------------------------------------------
621 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
623 if (widget
->window
!= gdk_event
->window
) return TRUE
;
624 if (!win
->HasVMT()) return TRUE
;
625 if (g_blockEventsOnDrag
) return TRUE
;
628 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
630 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
631 event
.SetEventObject( win
);
633 if (win
->GetEventHandler()->ProcessEvent( event
))
634 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
639 //-----------------------------------------------------------------------------
640 // "value_changed" from m_vAdjust
641 //-----------------------------------------------------------------------------
643 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
645 if (g_blockEventsOnDrag
) return;
648 printf( "OnVScroll from " );
649 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
650 printf( win->GetClassInfo()->GetClassName() );
654 if (!win
->HasVMT()) return;
656 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
657 if (fabs(diff
) < 0.2) return;
659 wxEventType command
= wxEVT_NULL
;
661 float line_step
= win
->m_vAdjust
->step_increment
;
662 float page_step
= win
->m_vAdjust
->page_increment
;
664 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
665 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
666 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
667 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
668 else command
= wxEVT_SCROLL_THUMBTRACK
;
670 int value
= (int)(win
->m_vAdjust
->value
+0.5);
672 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
673 event
.SetEventObject( win
);
674 win
->GetEventHandler()->ProcessEvent( event
);
677 //-----------------------------------------------------------------------------
678 // "value_changed" from m_hAdjust
679 //-----------------------------------------------------------------------------
681 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
683 if (g_blockEventsOnDrag
) return;
686 printf( "OnHScroll from " );
687 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
688 printf( win->GetClassInfo()->GetClassName() );
692 if (!win
->HasVMT()) return;
694 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
695 if (fabs(diff
) < 0.2) return;
697 wxEventType command
= wxEVT_NULL
;
699 float line_step
= win
->m_hAdjust
->step_increment
;
700 float page_step
= win
->m_hAdjust
->page_increment
;
702 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
703 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
704 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
705 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
706 else command
= wxEVT_SCROLL_THUMBTRACK
;
708 int value
= (int)(win
->m_hAdjust
->value
+0.5);
710 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
711 event
.SetEventObject( win
);
712 win
->GetEventHandler()->ProcessEvent( event
);
715 //-----------------------------------------------------------------------------
716 // "changed" from m_vAdjust
717 //-----------------------------------------------------------------------------
719 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
721 if (g_blockEventsOnDrag
) return;
724 printf( "OnVScroll change from " );
725 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
726 printf( win->GetClassInfo()->GetClassName() );
730 if (!win
->HasVMT()) return;
732 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
733 int value
= (int)(win
->m_vAdjust
->value
+0.5);
735 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
736 event
.SetEventObject( win
);
737 win
->GetEventHandler()->ProcessEvent( event
);
740 //-----------------------------------------------------------------------------
741 // "changed" from m_hAdjust
742 //-----------------------------------------------------------------------------
744 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
746 if (g_blockEventsOnDrag
) return;
749 printf( "OnHScroll change from " );
750 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
751 printf( win->GetClassInfo()->GetClassName() );
755 if (!win
->HasVMT()) return;
757 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
758 int value
= (int)(win
->m_hAdjust
->value
+0.5);
760 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
761 event
.SetEventObject( win
);
762 win
->GetEventHandler()->ProcessEvent( event
);
765 //-----------------------------------------------------------------------------
766 // "drop_data_available_event"
767 //-----------------------------------------------------------------------------
769 static void gtk_window_drop_callback( GtkWidget
*widget
, GdkEvent
*event
, wxWindow
*win
)
771 if (!win
->HasVMT()) return;
773 if (win
->GetDropTarget())
777 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
778 win
->GetDropTarget()->Drop( event
, x
, y
);
782 g_free (event->dropdataavailable.data);
783 g_free (event->dropdataavailable.data_type);
787 //-----------------------------------------------------------------------------
789 //-----------------------------------------------------------------------------
791 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
793 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
794 EVT_SIZE(wxWindow::OnSize
)
795 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
796 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
797 EVT_IDLE(wxWindow::OnIdle
)
802 m_widget
= (GtkWidget
*) NULL
;
803 m_wxwindow
= (GtkWidget
*) NULL
;
804 m_parent
= (wxWindow
*) NULL
;
805 m_children
.DeleteContents( FALSE
);
815 m_eventHandler
= this;
816 m_windowValidator
= (wxValidator
*) NULL
;
818 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
819 m_font
= *wxSWISS_FONT
;
821 m_windowName
= "noname";
822 m_constraints
= (wxLayoutConstraints
*) NULL
;
823 m_constraintsInvolvedIn
= (wxList
*) NULL
;
824 m_windowSizer
= (wxSizer
*) NULL
;
825 m_sizerParent
= (wxWindow
*) NULL
;
826 m_autoLayout
= FALSE
;
830 m_hasScrolling
= FALSE
;
831 m_hAdjust
= (GtkAdjustment
*) NULL
;
832 m_vAdjust
= (GtkAdjustment
*) NULL
;
833 m_oldHorizontalPos
= 0.0;
834 m_oldVerticalPos
= 0.0;
837 m_pDropTarget
= (wxDropTarget
*) NULL
;
839 m_hasOwnStyle
= FALSE
;
842 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
843 const wxPoint
&pos
, const wxSize
&size
,
844 long style
, const wxString
&name
)
850 m_cursor
= (wxCursor
*) NULL
;
852 PreCreation( parent
, id
, pos
, size
, style
, name
);
854 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
855 m_hasScrolling
= TRUE
;
857 GtkScrolledWindow
*s_window
;
858 s_window
= GTK_SCROLLED_WINDOW(m_widget
);
860 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
861 scroll_class
->scrollbar_spacing
= 0;
863 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
865 m_oldHorizontalPos
= 0.0;
866 m_oldVerticalPos
= 0.0;
868 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
869 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
871 gtk_signal_connect (GTK_OBJECT (m_hAdjust
), "value_changed",
872 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
873 gtk_signal_connect (GTK_OBJECT (m_vAdjust
), "value_changed",
874 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
876 gtk_signal_connect (GTK_OBJECT (m_hAdjust
), "changed",
877 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
878 gtk_signal_connect (GTK_OBJECT (m_vAdjust
), "changed",
879 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
881 GtkViewport
*viewport
;
882 viewport
= GTK_VIEWPORT(s_window
->viewport
);
884 if (m_windowStyle
& wxRAISED_BORDER
)
886 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
888 else if (m_windowStyle
& wxSUNKEN_BORDER
)
890 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
894 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
897 m_wxwindow
= gtk_myfixed_new();
899 if (m_wxwindow
) GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
901 if (m_windowStyle
& wxTAB_TRAVERSAL
== wxTAB_TRAVERSAL
)
902 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
904 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
906 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
908 // shut the viewport up
909 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
910 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
912 // I _really_ don't want scrollbars in the beginning
913 m_vAdjust
->lower
= 0.0;
914 m_vAdjust
->upper
= 1.0;
915 m_vAdjust
->value
= 0.0;
916 m_vAdjust
->step_increment
= 1.0;
917 m_vAdjust
->page_increment
= 1.0;
918 m_vAdjust
->page_size
= 5.0;
919 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
920 m_hAdjust
->lower
= 0.0;
921 m_hAdjust
->upper
= 1.0;
922 m_hAdjust
->value
= 0.0;
923 m_hAdjust
->step_increment
= 1.0;
924 m_hAdjust
->page_increment
= 1.0;
925 m_hAdjust
->page_size
= 5.0;
926 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
928 gtk_widget_show( m_wxwindow
);
937 wxWindow::~wxWindow(void)
941 if (m_pDropTarget
) delete m_pDropTarget
;
943 if (m_parent
) m_parent
->RemoveChild( this );
944 if (m_widget
) Show( FALSE
);
948 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
950 if (m_widget
) gtk_widget_destroy( m_widget
);
954 DeleteRelatedConstraints();
957 // This removes any dangling pointers to this window
958 // in other windows' constraintsInvolvedIn lists.
959 UnsetConstraints(m_constraints
);
960 delete m_constraints
;
961 m_constraints
= (wxLayoutConstraints
*) NULL
;
965 delete m_windowSizer
;
966 m_windowSizer
= (wxSizer
*) NULL
;
968 // If this is a child of a sizer, remove self from parent
969 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
971 // Just in case the window has been Closed, but
972 // we're then deleting immediately: don't leave
973 // dangling pointers.
974 wxPendingDelete
.DeleteObject(this);
976 // Just in case we've loaded a top-level window via
977 // wxWindow::LoadNativeDialog but we weren't a dialog
979 wxTopLevelWindows
.DeleteObject(this);
981 if (m_windowValidator
) delete m_windowValidator
;
984 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
985 const wxPoint
&pos
, const wxSize
&size
,
986 long style
, const wxString
&name
)
988 if (m_needParent
&& (parent
== NULL
))
989 wxFatalError( "Need complete parent.", name
);
991 m_widget
= (GtkWidget
*) NULL
;
994 m_children
.DeleteContents( FALSE
);
998 if (m_width
== -1) m_width
= 20;
1000 if (m_height
== -1) m_height
= 20;
1006 m_eventHandler
= this;
1009 if (m_cursor
== NULL
)
1010 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1011 m_font
= *wxSWISS_FONT
;
1012 m_backgroundColour
= wxWHITE
;
1013 m_foregroundColour
= wxBLACK
;
1014 m_windowStyle
= style
;
1015 m_windowName
= name
;
1016 m_constraints
= (wxLayoutConstraints
*) NULL
;
1017 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1018 m_windowSizer
= (wxSizer
*) NULL
;
1019 m_sizerParent
= (wxWindow
*) NULL
;
1020 m_autoLayout
= FALSE
;
1021 m_pDropTarget
= (wxDropTarget
*) NULL
;
1023 m_windowValidator
= (wxValidator
*) NULL
;
1024 m_hasOwnStyle
= FALSE
;
1027 void wxWindow::PostCreation(void)
1029 if (m_parent
) m_parent
->AddChild( this );
1033 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1034 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1036 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1037 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1040 ConnectWidget( GetConnectWidget() );
1042 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1046 gtk_widget_realize( m_wxwindow
);
1047 gdk_gc_set_exposures( m_wxwindow
->style
->fg_gc
[0], TRUE
);
1050 SetCursor( wxSTANDARD_CURSOR
);
1055 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1057 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1058 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1060 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1061 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1063 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1064 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1066 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1067 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1069 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1070 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1072 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1073 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1075 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1076 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1078 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1079 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1082 bool wxWindow::HasVMT(void)
1087 bool wxWindow::Close( bool force
)
1089 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1090 event
.SetEventObject(this);
1091 event
.SetForce(force
);
1093 return GetEventHandler()->ProcessEvent(event
);
1096 bool wxWindow::Destroy(void)
1103 bool wxWindow::DestroyChildren(void)
1108 while ((node
= GetChildren()->First()) != (wxNode
*)NULL
)
1111 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1114 if (GetChildren()->Member(child
)) delete node
;
1121 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1123 // are we to set fonts here ?
1126 void wxWindow::ImplementSetSize(void)
1128 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1129 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1130 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_minWidth
;
1131 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_minHeight
;
1132 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1135 void wxWindow::ImplementSetPosition(void)
1137 if (IS_KIND_OF(this,wxFrame
) || IS_KIND_OF(this,wxDialog
))
1139 if ((m_x
!= -1) || (m_y
!= -1))
1140 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
1146 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1150 if ((m_parent
) && (m_parent
->m_wxwindow
))
1151 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
, m_y
);
1153 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1156 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1158 if (m_resizing
) return; // I don't like recursions
1166 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1168 if (newX
== -1) newX
= m_x
;
1169 if (newY
== -1) newY
= m_y
;
1170 if (newW
== -1) newW
= m_width
;
1171 if (newH
== -1) newH
= m_height
;
1174 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1176 if (newW
== -1) newW
= 80;
1179 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1181 if (newH
== -1) newH
= 26;
1184 if ((m_x
!= newX
) || (m_y
!= newY
) || (!m_sizeSet
))
1188 ImplementSetPosition();
1190 if ((m_width
!= newW
) || (m_height
!= newH
) || (!m_sizeSet
))
1198 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1199 event
.SetEventObject( this );
1200 ProcessEvent( event
);
1205 void wxWindow::SetSize( int width
, int height
)
1207 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1210 void wxWindow::Move( int x
, int y
)
1212 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1215 void wxWindow::GetSize( int *width
, int *height
) const
1217 if (width
) (*width
) = m_width
;
1218 if (height
) (*height
) = m_height
;
1221 void wxWindow::SetClientSize( int width
, int height
)
1225 SetSize( width
, height
);
1232 if (!m_hasScrolling
)
1235 do we have sunken dialogs ?
1237 GtkStyleClass *window_class = m_wxwindow->style->klass;
1239 dw += 2 * window_class->xthickness;
1240 dh += 2 * window_class->ythickness;
1245 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1246 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1248 GtkWidget
*viewport
= scroll_window
->viewport
;
1249 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1251 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1252 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1254 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1255 (m_windowStyle
& wxSUNKEN_BORDER
))
1257 dw
+= 2 * viewport_class
->xthickness
;
1258 dh
+= 2 * viewport_class
->ythickness
;
1261 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1263 dw
+= vscrollbar
->allocation
.width
;
1264 dw
+= scroll_class
->scrollbar_spacing
;
1267 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1269 dh
+= hscrollbar
->allocation
.height
;
1270 dw
+= scroll_class
->scrollbar_spacing
;
1274 SetSize( width
+dw
, height
+dh
);
1278 void wxWindow::GetClientSize( int *width
, int *height
) const
1282 if (width
) (*width
) = m_width
;
1283 if (height
) (*height
) = m_height
;
1290 if (!m_hasScrolling
)
1293 do we have sunken dialogs ?
1295 GtkStyleClass *window_class = m_wxwindow->style->klass;
1297 dw += 2 * window_class->xthickness;
1298 dh += 2 * window_class->ythickness;
1303 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1304 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1306 GtkWidget
*viewport
= scroll_window
->viewport
;
1307 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1309 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1310 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1312 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1313 (m_windowStyle
& wxSUNKEN_BORDER
))
1315 dw
+= 2 * viewport_class
->xthickness
;
1316 dh
+= 2 * viewport_class
->ythickness
;
1319 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1321 // dw += vscrollbar->allocation.width;
1322 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1323 dw
+= scroll_class
->scrollbar_spacing
;
1326 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1328 // dh += hscrollbar->allocation.height;
1330 dh
+= scroll_class
->scrollbar_spacing
;
1334 if (width
) (*width
) = m_width
- dw
;
1335 if (height
) (*height
) = m_height
- dh
;
1339 void wxWindow::GetPosition( int *x
, int *y
) const
1345 void wxWindow::ClientToScreen( int *x
, int *y
)
1347 GdkWindow
*source
= (GdkWindow
*) NULL
;
1349 source
= m_wxwindow
->window
;
1351 source
= m_widget
->window
;
1355 gdk_window_get_origin( source
, &org_x
, &org_y
);
1359 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1361 org_x
+= m_widget
->allocation
.x
;
1362 org_y
+= m_widget
->allocation
.y
;
1370 void wxWindow::ScreenToClient( int *x
, int *y
)
1372 GdkWindow
*source
= (GdkWindow
*) NULL
;
1374 source
= m_wxwindow
->window
;
1376 source
= m_widget
->window
;
1380 gdk_window_get_origin( source
, &org_x
, &org_y
);
1384 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1386 org_x
+= m_widget
->allocation
.x
;
1387 org_y
+= m_widget
->allocation
.y
;
1395 void wxWindow::Centre( int direction
)
1397 if (IS_KIND_OF(this,wxDialog
) || IS_KIND_OF(this,wxFrame
))
1399 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (gdk_screen_width () - m_width
) / 2;
1400 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (gdk_screen_height () - m_height
) / 2;
1401 ImplementSetPosition();
1409 m_parent
->GetSize( &p_w
, &p_h
);
1410 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (p_w
- m_width
) / 2;
1411 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (p_h
- m_height
) / 2;
1412 ImplementSetPosition();
1417 void wxWindow::Fit(void)
1421 wxNode
*node
= GetChildren()->First();
1424 wxWindow
*win
= (wxWindow
*)node
->Data();
1426 win
->GetPosition(&wx
, &wy
);
1427 win
->GetSize(&ww
, &wh
);
1428 if ( wx
+ ww
> maxX
)
1430 if ( wy
+ wh
> maxY
)
1433 node
= node
->Next();
1435 SetClientSize(maxX
+ 5, maxY
+ 10);
1438 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1446 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1448 //if (GetAutoLayout()) Layout();
1451 bool wxWindow::Show( bool show
)
1454 gtk_widget_show( m_widget
);
1456 gtk_widget_hide( m_widget
);
1461 void wxWindow::Enable( bool enable
)
1463 m_isEnabled
= enable
;
1464 gtk_widget_set_sensitive( m_widget
, enable
);
1465 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1468 int wxWindow::GetCharHeight(void) const
1470 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1471 return font
->ascent
+ font
->descent
;
1474 int wxWindow::GetCharWidth(void) const
1476 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1477 return gdk_string_width( font
, "H" );
1480 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1481 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1483 wxFont fontToUse
= m_font
;
1484 if (theFont
) fontToUse
= *theFont
;
1486 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1487 if (x
) (*x
) = gdk_string_width( font
, string
);
1488 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1489 if (descent
) (*descent
) = font
->descent
;
1490 if (externalLeading
) (*externalLeading
) = 0; // ??
1493 void wxWindow::MakeModal( bool modal
)
1496 // Disable all other windows
1497 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1499 wxNode
*node
= wxTopLevelWindows
.First();
1502 wxWindow
*win
= (wxWindow
*)node
->Data();
1504 win
->Enable(!modal
);
1506 node
= node
->Next();
1511 void wxWindow::SetFocus(void)
1513 GtkWidget
*connect_widget
= GetConnectWidget();
1516 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) && !GTK_WIDGET_HAS_FOCUS (connect_widget
) )
1518 gtk_widget_grab_focus (connect_widget
);
1523 bool wxWindow::OnClose(void)
1528 void wxWindow::AddChild( wxWindow
*child
)
1530 // Addchild is (often) called before the program
1531 // has left the parents constructor so that no
1532 // virtual tables work yet. The approach below
1533 // practically imitates virtual tables, i.e. it
1534 // implements a different AddChild() behaviour
1535 // for wxFrame, wxDialog, wxWindow and
1536 // wxMDIParentFrame.
1538 // wxFrame and wxDialog as children aren't placed into the parents
1540 if (( IS_KIND_OF(child
,wxFrame
) || IS_KIND_OF(child
,wxDialog
) ) &&
1541 (!IS_KIND_OF(child
,wxMDIChildFrame
)))
1543 m_children
.Append( child
);
1545 if ((child
->m_x
!= -1) && (child
->m_y
!= -1))
1546 gtk_widget_set_uposition( child
->m_widget
, child
->m_x
, child
->m_y
);
1551 // In the case of an wxMDIChildFrame descendant, we use the
1552 // client windows's AddChild()
1554 if (IS_KIND_OF(this,wxMDIParentFrame
))
1556 if (IS_KIND_OF(child
,wxMDIChildFrame
))
1558 wxMDIClientWindow
*client
= ((wxMDIParentFrame
*)this)->GetClientWindow();
1561 client
->AddChild( child
);
1567 // wxNotebook is very special, so it has a private AddChild()
1569 if (IS_KIND_OF(this,wxNotebook
))
1571 wxNotebook
*tab
= (wxNotebook
*)this;
1572 tab
->AddChild( child
);
1576 // wxFrame has a private AddChild
1578 if (IS_KIND_OF(this,wxFrame
) && !IS_KIND_OF(this,wxMDIChildFrame
))
1580 wxFrame
*frame
= (wxFrame
*)this;
1581 frame
->AddChild( child
);
1587 m_children
.Append( child
);
1588 if (m_wxwindow
) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), child
->m_widget
,
1589 child
->m_x
, child
->m_y
);
1591 gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height
);
1594 wxList
*wxWindow::GetChildren(void)
1596 return (&m_children
);
1599 void wxWindow::RemoveChild( wxWindow
*child
)
1602 GetChildren()->DeleteObject( child
);
1603 child
->m_parent
= (wxWindow
*) NULL
;
1606 void wxWindow::SetReturnCode( int retCode
)
1608 m_retCode
= retCode
;
1611 int wxWindow::GetReturnCode(void)
1616 void wxWindow::Raise(void)
1618 if (m_widget
) gdk_window_raise( m_widget
->window
);
1621 void wxWindow::Lower(void)
1623 if (m_widget
) gdk_window_lower( m_widget
->window
);
1626 wxEvtHandler
*wxWindow::GetEventHandler(void)
1628 return m_eventHandler
;
1631 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
1633 m_eventHandler
= handler
;
1636 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
1638 handler
->SetNextHandler(GetEventHandler());
1639 SetEventHandler(handler
);
1642 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
1644 if ( GetEventHandler() )
1646 wxEvtHandler
*handlerA
= GetEventHandler();
1647 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
1648 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
1649 SetEventHandler(handlerB
);
1650 if ( deleteHandler
)
1653 return (wxEvtHandler
*) NULL
;
1659 return (wxEvtHandler
*) NULL
;
1662 wxValidator
*wxWindow::GetValidator(void)
1664 return m_windowValidator
;
1667 void wxWindow::SetValidator( const wxValidator
& validator
)
1669 if (m_windowValidator
) delete m_windowValidator
;
1670 m_windowValidator
= validator
.Clone();
1671 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
1674 bool wxWindow::IsBeingDeleted(void)
1679 void wxWindow::SetId( wxWindowID id
)
1684 wxWindowID
wxWindow::GetId(void)
1689 void wxWindow::SetCursor( const wxCursor
&cursor
)
1691 wxASSERT(m_cursor
!= NULL
);
1693 if (m_cursor
!= NULL
)
1694 if (*m_cursor
== cursor
)
1696 (*m_cursor
) = cursor
;
1697 if (m_widget
->window
)
1698 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
1699 if (m_wxwindow
&& m_wxwindow
->window
)
1700 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
1703 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
1705 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
1708 gdk_window_clear_area( m_wxwindow
->window
,
1722 GetClientSize( &w
, &h
);
1724 GdkRectangle gdk_rect
;
1728 gdk_rect
.height
= h
;
1729 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1734 GdkRectangle gdk_rect
;
1735 gdk_rect
.x
= rect
->x
;
1736 gdk_rect
.y
= rect
->y
;
1737 gdk_rect
.width
= rect
->width
;
1738 gdk_rect
.height
= rect
->height
;
1741 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1743 gtk_widget_draw( m_widget
, &gdk_rect
);
1747 wxRegion
wxWindow::GetUpdateRegion() const
1749 return m_updateRegion
;
1752 bool wxWindow::IsExposed( int x
, int y
) const
1754 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
1757 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
1759 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
1762 bool wxWindow::IsExposed( const wxPoint
& pt
) const
1764 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
1767 bool wxWindow::IsExposed( const wxRect
& rect
) const
1769 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
1772 void wxWindow::Clear(void)
1774 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
1777 wxColour
wxWindow::GetBackgroundColour(void) const
1779 return m_backgroundColour
;
1782 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
1784 m_backgroundColour
= colour
;
1787 m_backgroundColour
.CalcPixel( m_wxwindow
->style
->colormap
);
1788 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
1789 gdk_window_clear( m_wxwindow
->window
);
1794 wxColour
wxWindow::GetForegroundColour(void) const
1796 return m_foregroundColour
;
1799 void wxWindow::SetForegroundColour( const wxColour
&colour
)
1801 m_foregroundColour
= colour
;
1804 bool wxWindow::Validate(void)
1806 wxNode
*node
= GetChildren()->First();
1809 wxWindow
*child
= (wxWindow
*)node
->Data();
1810 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
1812 node
= node
->Next();
1817 bool wxWindow::TransferDataToWindow(void)
1819 wxNode
*node
= GetChildren()->First();
1822 wxWindow
*child
= (wxWindow
*)node
->Data();
1823 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
1824 !child
->GetValidator()->TransferToWindow() )
1826 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
1829 node
= node
->Next();
1834 bool wxWindow::TransferDataFromWindow(void)
1836 wxNode
*node
= GetChildren()->First();
1839 wxWindow
*child
= (wxWindow
*)node
->Data();
1840 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
1842 node
= node
->Next();
1847 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
1849 m_acceleratorTable
= accel
;
1852 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
1854 TransferDataToWindow();
1857 void wxWindow::InitDialog(void)
1859 wxInitDialogEvent
event(GetId());
1860 event
.SetEventObject( this );
1861 GetEventHandler()->ProcessEvent(event
);
1864 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
1866 menu
->SetInvokingWindow( win
);
1867 wxNode
*node
= menu
->m_items
.First();
1870 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
1871 if (menuitem
->IsSubMenu())
1872 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
1873 node
= node
->Next();
1877 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
1879 SetInvokingWindow( menu
, this );
1880 gtk_menu_popup( GTK_MENU(menu
->m_menu
), (GtkWidget
*) NULL
, (GtkWidget
*) NULL
, (GtkMenuPositionFunc
) NULL
, NULL
, 0, 0 );
1884 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
1886 GtkWidget
*dnd_widget
= GetConnectWidget();
1890 gtk_signal_disconnect_by_func( GTK_OBJECT(dnd_widget
),
1891 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
1893 m_pDropTarget
->UnregisterWidget( dnd_widget
);
1894 delete m_pDropTarget
;
1896 m_pDropTarget
= dropTarget
;
1899 m_pDropTarget
->RegisterWidget( dnd_widget
);
1901 gtk_signal_connect( GTK_OBJECT(dnd_widget
), "drop_data_available_event",
1902 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
1906 wxDropTarget
*wxWindow::GetDropTarget() const
1908 return m_pDropTarget
;
1911 GtkWidget
* wxWindow::GetConnectWidget(void)
1913 GtkWidget
*connect_widget
= m_widget
;
1914 if (m_wxwindow
) connect_widget
= m_wxwindow
;
1916 return connect_widget
;
1919 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
1921 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
1922 return (window
== m_widget
->window
);
1925 void wxWindow::SetFont( const wxFont
&font
)
1927 if (((wxFont
*)&font
)->Ok())
1930 m_font
= *wxSWISS_FONT
;
1932 GtkStyle
*style
= (GtkStyle
*) NULL
;
1935 m_hasOwnStyle
= TRUE
;
1936 style
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
1940 style
= gtk_widget_get_style( m_widget
);
1943 gdk_font_unref( style
->font
);
1944 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
1946 gtk_widget_set_style( m_widget
, style
);
1949 wxFont
*wxWindow::GetFont(void)
1954 void wxWindow::SetWindowStyleFlag( long flag
)
1956 m_windowStyle
= flag
;
1959 long wxWindow::GetWindowStyleFlag(void) const
1961 return m_windowStyle
;
1964 void wxWindow::CaptureMouse(void)
1966 GtkWidget
*connect_widget
= GetConnectWidget();
1967 gtk_grab_add( connect_widget
);
1968 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
1970 (GDK_BUTTON_PRESS_MASK
|
1971 GDK_BUTTON_RELEASE_MASK
|
1972 GDK_POINTER_MOTION_MASK
),
1973 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
1976 void wxWindow::ReleaseMouse(void)
1978 GtkWidget
*connect_widget
= GetConnectWidget();
1979 gtk_grab_remove( connect_widget
);
1980 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
1983 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
1987 wxString
wxWindow::GetTitle(void) const
1989 return (wxString
&)m_windowName
;
1992 wxString
wxWindow::GetLabel(void) const
1997 void wxWindow::SetName( const wxString
&name
)
1999 m_windowName
= name
;
2002 wxString
wxWindow::GetName(void) const
2004 return (wxString
&)m_windowName
;
2007 bool wxWindow::IsShown(void) const
2012 bool wxWindow::IsRetained(void)
2017 wxWindow
*wxWindow::FindWindow( long id
)
2019 if (id
== m_windowId
) return this;
2020 wxNode
*node
= m_children
.First();
2023 wxWindow
*child
= (wxWindow
*)node
->Data();
2024 wxWindow
*res
= child
->FindWindow( id
);
2025 if (res
) return res
;
2026 node
= node
->Next();
2028 return (wxWindow
*) NULL
;
2031 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2033 if (name
== m_windowName
) return this;
2034 wxNode
*node
= m_children
.First();
2037 wxWindow
*child
= (wxWindow
*)node
->Data();
2038 wxWindow
*res
= child
->FindWindow( name
);
2039 if (res
) return res
;
2040 node
= node
->Next();
2042 return (wxWindow
*) NULL
;
2045 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2046 int range
, bool WXUNUSED(refresh
) )
2048 if (!m_wxwindow
) return;
2050 if (orient
== wxHORIZONTAL
)
2052 float fpos
= (float)pos
;
2053 m_oldHorizontalPos
= fpos
;
2054 float frange
= (float)range
;
2055 float fthumb
= (float)thumbVisible
;
2057 if ((fabs(fpos
-m_hAdjust
->value
) < 0.2) &&
2058 (fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2059 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2062 m_hAdjust
->lower
= 0.0;
2063 m_hAdjust
->upper
= frange
;
2064 m_hAdjust
->value
= fpos
;
2065 m_hAdjust
->step_increment
= 1.0;
2066 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2067 m_hAdjust
->page_size
= fthumb
;
2071 float fpos
= (float)pos
;
2072 m_oldVerticalPos
= fpos
;
2073 float frange
= (float)range
;
2074 float fthumb
= (float)thumbVisible
;
2076 if ((fabs(fpos
-m_vAdjust
->value
) < 0.2) &&
2077 (fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2078 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2081 m_vAdjust
->lower
= 0.0;
2082 m_vAdjust
->upper
= frange
;
2083 m_vAdjust
->value
= fpos
;
2084 m_vAdjust
->step_increment
= 1.0;
2085 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2086 m_vAdjust
->page_size
= fthumb
;
2089 if (m_wxwindow
->window
)
2091 if (orient
== wxHORIZONTAL
)
2092 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2094 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2096 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2100 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2102 if (!m_wxwindow
) return;
2104 if (orient
== wxHORIZONTAL
)
2106 float fpos
= (float)pos
;
2107 m_oldHorizontalPos
= fpos
;
2109 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2110 m_hAdjust
->value
= fpos
;
2114 float fpos
= (float)pos
;
2115 m_oldVerticalPos
= fpos
;
2116 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2117 m_vAdjust
->value
= fpos
;
2120 if (m_wxwindow
->window
)
2122 if (orient
== wxHORIZONTAL
)
2123 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2125 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2129 int wxWindow::GetScrollThumb( int orient
) const
2131 if (!m_wxwindow
) return 0;
2133 if (orient
== wxHORIZONTAL
)
2134 return (int)(m_hAdjust
->page_size
+0.5);
2136 return (int)(m_vAdjust
->page_size
+0.5);
2139 int wxWindow::GetScrollPos( int orient
) const
2141 if (!m_wxwindow
) return 0;
2143 if (orient
== wxHORIZONTAL
)
2144 return (int)(m_hAdjust
->value
+0.5);
2146 return (int)(m_vAdjust
->value
+0.5);
2149 int wxWindow::GetScrollRange( int orient
) const
2151 if (!m_wxwindow
) return 0;
2153 if (orient
== wxHORIZONTAL
)
2154 return (int)(m_hAdjust
->upper
+0.5);
2156 return (int)(m_vAdjust
->upper
+0.5);
2159 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2161 if (!m_wxwindow
) return;
2164 bool refresh = FALSE;
2166 if ((m_drawingOffsetX == 0) && (m_drawingOffsetY == 0))
2168 m_drawingOffsetX = -16000;
2169 m_drawingOffsetY = -16000;
2174 m_drawingOffsetX += dx;
2175 m_drawingOffsetY += dy;
2178 // printf( "X: %d Y: %d \n", (int)m_drawingOffsetX, (int)m_drawingOffsetY );
2180 gtk_myfixed_set_offset( GTK_MYFIXED(m_wxwindow), m_drawingOffsetX, m_drawingOffsetY );
2182 if (refresh) Refresh();
2184 The code here is very nifty, but it doesn't work with
2185 overlapping windows...
2190 GetClientSize( &cw
, &ch
);
2192 int w
= cw
- abs(dx
);
2193 int h
= ch
- abs(dy
);
2194 if ((h
< 0) || (w
< 0))
2201 if (dx
< 0) s_x
= -dx
;
2202 if (dy
< 0) s_y
= -dy
;
2205 if (dx
> 0) d_x
= dx
;
2206 if (dy
> 0) d_y
= dy
;
2207 gdk_window_copy_area( m_wxwindow
->window
, m_wxwindow
->style
->fg_gc
[0], d_x
, d_y
,
2208 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2211 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2212 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2213 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2214 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2216 Refresh( TRUE
, &rect
);
2219 //-------------------------------------------------------------------------------------
2221 //-------------------------------------------------------------------------------------
2223 wxLayoutConstraints
*wxWindow::GetConstraints(void) const
2225 return m_constraints
;
2228 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2232 UnsetConstraints(m_constraints
);
2233 delete m_constraints
;
2235 m_constraints
= constraints
;
2238 // Make sure other windows know they're part of a 'meaningful relationship'
2239 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2240 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2241 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2242 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2243 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2244 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2245 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2246 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2247 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2248 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2249 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2250 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2251 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2252 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2253 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2254 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2260 void wxWindow::SetAutoLayout( bool autoLayout
)
2262 m_autoLayout
= autoLayout
;
2265 bool wxWindow::GetAutoLayout(void) const
2267 return m_autoLayout
;
2270 wxSizer
*wxWindow::GetSizer(void) const
2272 return m_windowSizer
;
2275 void wxWindow::SetSizerParent( wxWindow
*win
)
2277 m_sizerParent
= win
;
2280 wxWindow
*wxWindow::GetSizerParent(void) const
2282 return m_sizerParent
;
2285 // This removes any dangling pointers to this window
2286 // in other windows' constraintsInvolvedIn lists.
2287 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2291 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2292 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2293 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2294 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2295 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2296 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2297 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2298 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2299 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2300 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2301 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2302 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2303 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2304 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2305 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2306 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2310 // Back-pointer to other windows we're involved with, so if we delete
2311 // this window, we must delete any constraints we're involved with.
2312 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2314 if (!m_constraintsInvolvedIn
)
2315 m_constraintsInvolvedIn
= new wxList
;
2316 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2317 m_constraintsInvolvedIn
->Append(otherWin
);
2320 // REMOVE back-pointer to other windows we're involved with.
2321 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2323 if (m_constraintsInvolvedIn
)
2324 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2327 // Reset any constraints that mention this window
2328 void wxWindow::DeleteRelatedConstraints(void)
2330 if (m_constraintsInvolvedIn
)
2332 wxNode
*node
= m_constraintsInvolvedIn
->First();
2335 wxWindow
*win
= (wxWindow
*)node
->Data();
2336 wxNode
*next
= node
->Next();
2337 wxLayoutConstraints
*constr
= win
->GetConstraints();
2339 // Reset any constraints involving this window
2342 constr
->left
.ResetIfWin((wxWindow
*)this);
2343 constr
->top
.ResetIfWin((wxWindow
*)this);
2344 constr
->right
.ResetIfWin((wxWindow
*)this);
2345 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2346 constr
->width
.ResetIfWin((wxWindow
*)this);
2347 constr
->height
.ResetIfWin((wxWindow
*)this);
2348 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2349 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2354 delete m_constraintsInvolvedIn
;
2355 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2359 void wxWindow::SetSizer(wxSizer
*sizer
)
2361 m_windowSizer
= sizer
;
2363 sizer
->SetSizerParent((wxWindow
*)this);
2370 bool wxWindow::Layout(void)
2372 if (GetConstraints())
2375 GetClientSize(&w
, &h
);
2376 GetConstraints()->width
.SetValue(w
);
2377 GetConstraints()->height
.SetValue(h
);
2380 // If top level (one sizer), evaluate the sizer's constraints.
2384 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2385 GetSizer()->LayoutPhase1(&noChanges
);
2386 GetSizer()->LayoutPhase2(&noChanges
);
2387 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2392 // Otherwise, evaluate child constraints
2393 ResetConstraints(); // Mark all constraints as unevaluated
2394 DoPhase(1); // Just one phase need if no sizers involved
2396 SetConstraintSizes(); // Recursively set the real window sizes
2402 // Do a phase of evaluating constraints:
2403 // the default behaviour. wxSizers may do a similar
2404 // thing, but also impose their own 'constraints'
2405 // and order the evaluation differently.
2406 bool wxWindow::LayoutPhase1(int *noChanges
)
2408 wxLayoutConstraints
*constr
= GetConstraints();
2411 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2417 bool wxWindow::LayoutPhase2(int *noChanges
)
2427 // Do a phase of evaluating child constraints
2428 bool wxWindow::DoPhase(int phase
)
2430 int noIterations
= 0;
2431 int maxIterations
= 500;
2435 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2439 wxNode
*node
= GetChildren()->First();
2442 wxWindow
*child
= (wxWindow
*)node
->Data();
2443 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2445 wxLayoutConstraints
*constr
= child
->GetConstraints();
2448 if (succeeded
.Member(child
))
2453 int tempNoChanges
= 0;
2454 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2455 noChanges
+= tempNoChanges
;
2458 succeeded
.Append(child
);
2463 node
= node
->Next();
2470 void wxWindow::ResetConstraints(void)
2472 wxLayoutConstraints
*constr
= GetConstraints();
2475 constr
->left
.SetDone(FALSE
);
2476 constr
->top
.SetDone(FALSE
);
2477 constr
->right
.SetDone(FALSE
);
2478 constr
->bottom
.SetDone(FALSE
);
2479 constr
->width
.SetDone(FALSE
);
2480 constr
->height
.SetDone(FALSE
);
2481 constr
->centreX
.SetDone(FALSE
);
2482 constr
->centreY
.SetDone(FALSE
);
2484 wxNode
*node
= GetChildren()->First();
2487 wxWindow
*win
= (wxWindow
*)node
->Data();
2488 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2489 win
->ResetConstraints();
2490 node
= node
->Next();
2494 // Need to distinguish between setting the 'fake' size for
2495 // windows and sizers, and setting the real values.
2496 void wxWindow::SetConstraintSizes(bool recurse
)
2498 wxLayoutConstraints
*constr
= GetConstraints();
2499 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2500 constr
->width
.GetDone() && constr
->height
.GetDone())
2502 int x
= constr
->left
.GetValue();
2503 int y
= constr
->top
.GetValue();
2504 int w
= constr
->width
.GetValue();
2505 int h
= constr
->height
.GetValue();
2507 // If we don't want to resize this window, just move it...
2508 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2509 (constr
->height
.GetRelationship() != wxAsIs
))
2511 // Calls Layout() recursively. AAAGH. How can we stop that.
2512 // Simply take Layout() out of non-top level OnSizes.
2513 SizerSetSize(x
, y
, w
, h
);
2522 char *windowClass
= this->GetClassInfo()->GetClassName();
2525 if (GetName() == "")
2526 winName
= _("unnamed");
2528 winName
= GetName();
2529 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2530 if (!constr
->left
.GetDone())
2531 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2532 if (!constr
->right
.GetDone())
2533 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2534 if (!constr
->width
.GetDone())
2535 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2536 if (!constr
->height
.GetDone())
2537 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2538 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2543 wxNode
*node
= GetChildren()->First();
2546 wxWindow
*win
= (wxWindow
*)node
->Data();
2547 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2548 win
->SetConstraintSizes();
2549 node
= node
->Next();
2554 // This assumes that all sizers are 'on' the same
2555 // window, i.e. the parent of this window.
2556 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2558 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2559 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2563 m_sizerParent
->GetPosition(&xp
, &yp
);
2564 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2569 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2573 TransformSizerToActual(&xx
, &yy
);
2574 SetSize(xx
, yy
, w
, h
);
2577 void wxWindow::SizerMove(int x
, int y
)
2581 TransformSizerToActual(&xx
, &yy
);
2585 // Only set the size/position of the constraint (if any)
2586 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2588 wxLayoutConstraints
*constr
= GetConstraints();
2593 constr
->left
.SetValue(x
);
2594 constr
->left
.SetDone(TRUE
);
2598 constr
->top
.SetValue(y
);
2599 constr
->top
.SetDone(TRUE
);
2603 constr
->width
.SetValue(w
);
2604 constr
->width
.SetDone(TRUE
);
2608 constr
->height
.SetValue(h
);
2609 constr
->height
.SetDone(TRUE
);
2614 void wxWindow::MoveConstraint(int x
, int y
)
2616 wxLayoutConstraints
*constr
= GetConstraints();
2621 constr
->left
.SetValue(x
);
2622 constr
->left
.SetDone(TRUE
);
2626 constr
->top
.SetValue(y
);
2627 constr
->top
.SetDone(TRUE
);
2632 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2634 wxLayoutConstraints
*constr
= GetConstraints();
2637 *w
= constr
->width
.GetValue();
2638 *h
= constr
->height
.GetValue();
2644 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2646 wxLayoutConstraints
*constr
= GetConstraints();
2649 *w
= constr
->width
.GetValue();
2650 *h
= constr
->height
.GetValue();
2653 GetClientSize(w
, h
);
2656 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2658 wxLayoutConstraints
*constr
= GetConstraints();
2661 *x
= constr
->left
.GetValue();
2662 *y
= constr
->top
.GetValue();
2668 bool wxWindow::AcceptsFocus() const
2670 return IsEnabled() && IsShown();
2673 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )