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();
1888 DisconnectDnDWidget( dnd_widget
);
1890 if (m_pDropTarget
) delete m_pDropTarget
;
1891 m_pDropTarget
= dropTarget
;
1893 ConnectDnDWidget( dnd_widget
);
1896 wxDropTarget
*wxWindow::GetDropTarget() const
1898 return m_pDropTarget
;
1901 void wxWindow::ConnectDnDWidget( GtkWidget
*widget
)
1903 if (!m_pDropTarget
) return;
1905 m_pDropTarget
->RegisterWidget( widget
);
1907 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
1908 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
1911 void wxWindow::DisconnectDnDWidget( GtkWidget
*widget
)
1913 if (!m_pDropTarget
) return;
1915 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
1916 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
1918 m_pDropTarget
->UnregisterWidget( widget
);
1921 GtkWidget
* wxWindow::GetConnectWidget(void)
1923 GtkWidget
*connect_widget
= m_widget
;
1924 if (m_wxwindow
) connect_widget
= m_wxwindow
;
1926 return connect_widget
;
1929 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
1931 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
1932 return (window
== m_widget
->window
);
1935 void wxWindow::SetFont( const wxFont
&font
)
1937 if (((wxFont
*)&font
)->Ok())
1940 m_font
= *wxSWISS_FONT
;
1942 GtkStyle
*style
= (GtkStyle
*) NULL
;
1945 m_hasOwnStyle
= TRUE
;
1946 style
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
1950 style
= gtk_widget_get_style( m_widget
);
1953 gdk_font_unref( style
->font
);
1954 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
1956 gtk_widget_set_style( m_widget
, style
);
1959 wxFont
*wxWindow::GetFont(void)
1964 void wxWindow::SetWindowStyleFlag( long flag
)
1966 m_windowStyle
= flag
;
1969 long wxWindow::GetWindowStyleFlag(void) const
1971 return m_windowStyle
;
1974 void wxWindow::CaptureMouse(void)
1976 GtkWidget
*connect_widget
= GetConnectWidget();
1977 gtk_grab_add( connect_widget
);
1978 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
1980 (GDK_BUTTON_PRESS_MASK
|
1981 GDK_BUTTON_RELEASE_MASK
|
1982 GDK_POINTER_MOTION_MASK
),
1983 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
1986 void wxWindow::ReleaseMouse(void)
1988 GtkWidget
*connect_widget
= GetConnectWidget();
1989 gtk_grab_remove( connect_widget
);
1990 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
1993 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
1997 wxString
wxWindow::GetTitle(void) const
1999 return (wxString
&)m_windowName
;
2002 wxString
wxWindow::GetLabel(void) const
2007 void wxWindow::SetName( const wxString
&name
)
2009 m_windowName
= name
;
2012 wxString
wxWindow::GetName(void) const
2014 return (wxString
&)m_windowName
;
2017 bool wxWindow::IsShown(void) const
2022 bool wxWindow::IsRetained(void)
2027 wxWindow
*wxWindow::FindWindow( long id
)
2029 if (id
== m_windowId
) return this;
2030 wxNode
*node
= m_children
.First();
2033 wxWindow
*child
= (wxWindow
*)node
->Data();
2034 wxWindow
*res
= child
->FindWindow( id
);
2035 if (res
) return res
;
2036 node
= node
->Next();
2038 return (wxWindow
*) NULL
;
2041 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2043 if (name
== m_windowName
) return this;
2044 wxNode
*node
= m_children
.First();
2047 wxWindow
*child
= (wxWindow
*)node
->Data();
2048 wxWindow
*res
= child
->FindWindow( name
);
2049 if (res
) return res
;
2050 node
= node
->Next();
2052 return (wxWindow
*) NULL
;
2055 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2056 int range
, bool WXUNUSED(refresh
) )
2058 if (!m_wxwindow
) return;
2060 if (orient
== wxHORIZONTAL
)
2062 float fpos
= (float)pos
;
2063 m_oldHorizontalPos
= fpos
;
2064 float frange
= (float)range
;
2065 float fthumb
= (float)thumbVisible
;
2067 if ((fabs(fpos
-m_hAdjust
->value
) < 0.2) &&
2068 (fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2069 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2072 m_hAdjust
->lower
= 0.0;
2073 m_hAdjust
->upper
= frange
;
2074 m_hAdjust
->value
= fpos
;
2075 m_hAdjust
->step_increment
= 1.0;
2076 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2077 m_hAdjust
->page_size
= fthumb
;
2081 float fpos
= (float)pos
;
2082 m_oldVerticalPos
= fpos
;
2083 float frange
= (float)range
;
2084 float fthumb
= (float)thumbVisible
;
2086 if ((fabs(fpos
-m_vAdjust
->value
) < 0.2) &&
2087 (fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2088 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2091 m_vAdjust
->lower
= 0.0;
2092 m_vAdjust
->upper
= frange
;
2093 m_vAdjust
->value
= fpos
;
2094 m_vAdjust
->step_increment
= 1.0;
2095 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2096 m_vAdjust
->page_size
= fthumb
;
2099 if (m_wxwindow
->window
)
2101 if (orient
== wxHORIZONTAL
)
2102 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2104 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2106 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2110 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2112 if (!m_wxwindow
) return;
2114 if (orient
== wxHORIZONTAL
)
2116 float fpos
= (float)pos
;
2117 m_oldHorizontalPos
= fpos
;
2119 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2120 m_hAdjust
->value
= fpos
;
2124 float fpos
= (float)pos
;
2125 m_oldVerticalPos
= fpos
;
2126 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2127 m_vAdjust
->value
= fpos
;
2130 if (m_wxwindow
->window
)
2132 if (orient
== wxHORIZONTAL
)
2133 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2135 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2139 int wxWindow::GetScrollThumb( int orient
) const
2141 if (!m_wxwindow
) return 0;
2143 if (orient
== wxHORIZONTAL
)
2144 return (int)(m_hAdjust
->page_size
+0.5);
2146 return (int)(m_vAdjust
->page_size
+0.5);
2149 int wxWindow::GetScrollPos( int orient
) const
2151 if (!m_wxwindow
) return 0;
2153 if (orient
== wxHORIZONTAL
)
2154 return (int)(m_hAdjust
->value
+0.5);
2156 return (int)(m_vAdjust
->value
+0.5);
2159 int wxWindow::GetScrollRange( int orient
) const
2161 if (!m_wxwindow
) return 0;
2163 if (orient
== wxHORIZONTAL
)
2164 return (int)(m_hAdjust
->upper
+0.5);
2166 return (int)(m_vAdjust
->upper
+0.5);
2169 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2171 if (!m_wxwindow
) return;
2174 bool refresh = FALSE;
2176 if ((m_drawingOffsetX == 0) && (m_drawingOffsetY == 0))
2178 m_drawingOffsetX = -16000;
2179 m_drawingOffsetY = -16000;
2184 m_drawingOffsetX += dx;
2185 m_drawingOffsetY += dy;
2188 // printf( "X: %d Y: %d \n", (int)m_drawingOffsetX, (int)m_drawingOffsetY );
2190 gtk_myfixed_set_offset( GTK_MYFIXED(m_wxwindow), m_drawingOffsetX, m_drawingOffsetY );
2192 if (refresh) Refresh();
2194 The code here is very nifty, but it doesn't work with
2195 overlapping windows...
2200 GetClientSize( &cw
, &ch
);
2202 int w
= cw
- abs(dx
);
2203 int h
= ch
- abs(dy
);
2204 if ((h
< 0) || (w
< 0))
2211 if (dx
< 0) s_x
= -dx
;
2212 if (dy
< 0) s_y
= -dy
;
2215 if (dx
> 0) d_x
= dx
;
2216 if (dy
> 0) d_y
= dy
;
2217 gdk_window_copy_area( m_wxwindow
->window
, m_wxwindow
->style
->fg_gc
[0], d_x
, d_y
,
2218 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2221 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2222 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2223 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2224 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2226 Refresh( TRUE
, &rect
);
2229 //-------------------------------------------------------------------------------------
2231 //-------------------------------------------------------------------------------------
2233 wxLayoutConstraints
*wxWindow::GetConstraints(void) const
2235 return m_constraints
;
2238 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2242 UnsetConstraints(m_constraints
);
2243 delete m_constraints
;
2245 m_constraints
= constraints
;
2248 // Make sure other windows know they're part of a 'meaningful relationship'
2249 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2250 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2251 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2252 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2253 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2254 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2255 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2256 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2257 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2258 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2259 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2260 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2261 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2262 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2263 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2264 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2270 void wxWindow::SetAutoLayout( bool autoLayout
)
2272 m_autoLayout
= autoLayout
;
2275 bool wxWindow::GetAutoLayout(void) const
2277 return m_autoLayout
;
2280 wxSizer
*wxWindow::GetSizer(void) const
2282 return m_windowSizer
;
2285 void wxWindow::SetSizerParent( wxWindow
*win
)
2287 m_sizerParent
= win
;
2290 wxWindow
*wxWindow::GetSizerParent(void) const
2292 return m_sizerParent
;
2295 // This removes any dangling pointers to this window
2296 // in other windows' constraintsInvolvedIn lists.
2297 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2301 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2302 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2303 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2304 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2305 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2306 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2307 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2308 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2309 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2310 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2311 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2312 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2313 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2314 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2315 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2316 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2320 // Back-pointer to other windows we're involved with, so if we delete
2321 // this window, we must delete any constraints we're involved with.
2322 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2324 if (!m_constraintsInvolvedIn
)
2325 m_constraintsInvolvedIn
= new wxList
;
2326 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2327 m_constraintsInvolvedIn
->Append(otherWin
);
2330 // REMOVE back-pointer to other windows we're involved with.
2331 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2333 if (m_constraintsInvolvedIn
)
2334 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2337 // Reset any constraints that mention this window
2338 void wxWindow::DeleteRelatedConstraints(void)
2340 if (m_constraintsInvolvedIn
)
2342 wxNode
*node
= m_constraintsInvolvedIn
->First();
2345 wxWindow
*win
= (wxWindow
*)node
->Data();
2346 wxNode
*next
= node
->Next();
2347 wxLayoutConstraints
*constr
= win
->GetConstraints();
2349 // Reset any constraints involving this window
2352 constr
->left
.ResetIfWin((wxWindow
*)this);
2353 constr
->top
.ResetIfWin((wxWindow
*)this);
2354 constr
->right
.ResetIfWin((wxWindow
*)this);
2355 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2356 constr
->width
.ResetIfWin((wxWindow
*)this);
2357 constr
->height
.ResetIfWin((wxWindow
*)this);
2358 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2359 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2364 delete m_constraintsInvolvedIn
;
2365 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2369 void wxWindow::SetSizer(wxSizer
*sizer
)
2371 m_windowSizer
= sizer
;
2373 sizer
->SetSizerParent((wxWindow
*)this);
2380 bool wxWindow::Layout(void)
2382 if (GetConstraints())
2385 GetClientSize(&w
, &h
);
2386 GetConstraints()->width
.SetValue(w
);
2387 GetConstraints()->height
.SetValue(h
);
2390 // If top level (one sizer), evaluate the sizer's constraints.
2394 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2395 GetSizer()->LayoutPhase1(&noChanges
);
2396 GetSizer()->LayoutPhase2(&noChanges
);
2397 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2402 // Otherwise, evaluate child constraints
2403 ResetConstraints(); // Mark all constraints as unevaluated
2404 DoPhase(1); // Just one phase need if no sizers involved
2406 SetConstraintSizes(); // Recursively set the real window sizes
2412 // Do a phase of evaluating constraints:
2413 // the default behaviour. wxSizers may do a similar
2414 // thing, but also impose their own 'constraints'
2415 // and order the evaluation differently.
2416 bool wxWindow::LayoutPhase1(int *noChanges
)
2418 wxLayoutConstraints
*constr
= GetConstraints();
2421 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2427 bool wxWindow::LayoutPhase2(int *noChanges
)
2437 // Do a phase of evaluating child constraints
2438 bool wxWindow::DoPhase(int phase
)
2440 int noIterations
= 0;
2441 int maxIterations
= 500;
2445 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2449 wxNode
*node
= GetChildren()->First();
2452 wxWindow
*child
= (wxWindow
*)node
->Data();
2453 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2455 wxLayoutConstraints
*constr
= child
->GetConstraints();
2458 if (succeeded
.Member(child
))
2463 int tempNoChanges
= 0;
2464 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2465 noChanges
+= tempNoChanges
;
2468 succeeded
.Append(child
);
2473 node
= node
->Next();
2480 void wxWindow::ResetConstraints(void)
2482 wxLayoutConstraints
*constr
= GetConstraints();
2485 constr
->left
.SetDone(FALSE
);
2486 constr
->top
.SetDone(FALSE
);
2487 constr
->right
.SetDone(FALSE
);
2488 constr
->bottom
.SetDone(FALSE
);
2489 constr
->width
.SetDone(FALSE
);
2490 constr
->height
.SetDone(FALSE
);
2491 constr
->centreX
.SetDone(FALSE
);
2492 constr
->centreY
.SetDone(FALSE
);
2494 wxNode
*node
= GetChildren()->First();
2497 wxWindow
*win
= (wxWindow
*)node
->Data();
2498 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2499 win
->ResetConstraints();
2500 node
= node
->Next();
2504 // Need to distinguish between setting the 'fake' size for
2505 // windows and sizers, and setting the real values.
2506 void wxWindow::SetConstraintSizes(bool recurse
)
2508 wxLayoutConstraints
*constr
= GetConstraints();
2509 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2510 constr
->width
.GetDone() && constr
->height
.GetDone())
2512 int x
= constr
->left
.GetValue();
2513 int y
= constr
->top
.GetValue();
2514 int w
= constr
->width
.GetValue();
2515 int h
= constr
->height
.GetValue();
2517 // If we don't want to resize this window, just move it...
2518 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2519 (constr
->height
.GetRelationship() != wxAsIs
))
2521 // Calls Layout() recursively. AAAGH. How can we stop that.
2522 // Simply take Layout() out of non-top level OnSizes.
2523 SizerSetSize(x
, y
, w
, h
);
2532 char *windowClass
= this->GetClassInfo()->GetClassName();
2535 if (GetName() == "")
2536 winName
= _("unnamed");
2538 winName
= GetName();
2539 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2540 if (!constr
->left
.GetDone())
2541 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2542 if (!constr
->right
.GetDone())
2543 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2544 if (!constr
->width
.GetDone())
2545 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2546 if (!constr
->height
.GetDone())
2547 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2548 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2553 wxNode
*node
= GetChildren()->First();
2556 wxWindow
*win
= (wxWindow
*)node
->Data();
2557 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2558 win
->SetConstraintSizes();
2559 node
= node
->Next();
2564 // This assumes that all sizers are 'on' the same
2565 // window, i.e. the parent of this window.
2566 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2568 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2569 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2573 m_sizerParent
->GetPosition(&xp
, &yp
);
2574 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2579 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2583 TransformSizerToActual(&xx
, &yy
);
2584 SetSize(xx
, yy
, w
, h
);
2587 void wxWindow::SizerMove(int x
, int y
)
2591 TransformSizerToActual(&xx
, &yy
);
2595 // Only set the size/position of the constraint (if any)
2596 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2598 wxLayoutConstraints
*constr
= GetConstraints();
2603 constr
->left
.SetValue(x
);
2604 constr
->left
.SetDone(TRUE
);
2608 constr
->top
.SetValue(y
);
2609 constr
->top
.SetDone(TRUE
);
2613 constr
->width
.SetValue(w
);
2614 constr
->width
.SetDone(TRUE
);
2618 constr
->height
.SetValue(h
);
2619 constr
->height
.SetDone(TRUE
);
2624 void wxWindow::MoveConstraint(int x
, int y
)
2626 wxLayoutConstraints
*constr
= GetConstraints();
2631 constr
->left
.SetValue(x
);
2632 constr
->left
.SetDone(TRUE
);
2636 constr
->top
.SetValue(y
);
2637 constr
->top
.SetDone(TRUE
);
2642 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2644 wxLayoutConstraints
*constr
= GetConstraints();
2647 *w
= constr
->width
.GetValue();
2648 *h
= constr
->height
.GetValue();
2654 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2656 wxLayoutConstraints
*constr
= GetConstraints();
2659 *w
= constr
->width
.GetValue();
2660 *h
= constr
->height
.GetValue();
2663 GetClientSize(w
, h
);
2666 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2668 wxLayoutConstraints
*constr
= GetConstraints();
2671 *x
= constr
->left
.GetValue();
2672 *y
= constr
->top
.GetValue();
2678 bool wxWindow::AcceptsFocus() const
2680 return IsEnabled() && IsShown();
2683 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )