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 "gdk/gdkkeysyms.h"
34 #include "wx/gtk/win_gtk.h"
35 #include "gdk/gdkprivate.h"
37 //-----------------------------------------------------------------------------
38 // documentation on internals
39 //-----------------------------------------------------------------------------
42 I have been asked several times about writing some documentation about
43 the GTK port of wxWindows, especially its internal structures. Obviously,
44 you cannot understand wxGTK without knowing a little about the GTK, but
45 some more information about what the wxWindow, which is the base class
46 for all other window classes, does seems required as well.
48 What does wxWindow do? It contains the common interface for the following
49 jobs of its descentants:
51 1) Define the rudimentary behaviour common to all window classes, such as
52 resizing, intercepting user input so as to make it possible to use these
53 events for special purposes in a derived class, window names etc.
55 2) Provide the possibility to contain and manage children, if the derived
56 class is allowed to contain children, which holds true for those window
57 classes, which do not display a native GTK widget. To name them, these
58 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
59 work classes are a special case and are handled a bit differently from
62 3) Provide the possibility to draw into a client area of a window. This,
63 too, only holds true for classes that do not display a native GTK widget
66 4) Provide the entire mechanism for scrolling widgets. This actaul inter-
67 face for this is usually in wxScrolledWidget, but the GTK implementation
70 5) A multitude of helper or extra methods for special purposes, such as
71 Drag'n'Drop, managing validators etc.
73 Normally one might expect, that one wxWindows class would always contain
74 one GTK widget. Under GTK, there is no such allround widget that has all
75 the functionality. Moreover, the GTK defines a client area as a different
76 widget from the actual widget you are handling. Last but not least some
77 special classes (e.g. wxFrame) handle different categories of widgets and
78 still have the possibility to draw something in the client area.
79 It was therefore required to write a special purpose GTK widget, that would
80 represent a client area in the sense of wxWindows capable to do the jobs
81 2), 3) and 4). I have written this class and it resides in win_gtk.c of
84 All windows must have a widget, with which they interact with other under-
85 lying GTK widget. It is this widget, e.g. that has to be resized etc and
86 thw wxWindow class has a member variable called m_widget which holds a
87 pointer to this widget. When the window class displays a GTK native widget,
88 this is the only GTK widget the class manages. When the class has a client
89 area for drawing into and for containing children it must have at least
90 one more GTK widget to handle (of the type GtkMyFixed, defined in win_gtk.c),
91 but there can be any number of widgets, handled by a class (e.g. the frame
92 class handles three). The common rule for all windows is only, that the
93 widget that interacts with the rest of GTK must be referenced in m_widget
94 and all other widgets must be children of this widget on the GTK level.
95 The top-most widget, which also represents the client area, must be in
96 the m_wxwindow field and must be of the type GtkMyFixed.
98 As I said, the window classes that display a GTK native widget only have
99 one widget, so in the case of e.g. the wxButton class m_widget holds a
100 pointer to a GtkButton widget. But windows with client areas (for drawing
101 and children) have a m_widget field that is a pointer to a GtkScrolled-
102 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
103 one is (in the GTK sense) a child of the GtkScrolledWindow.
105 If the m_wxwindow field is set, then all input to this widget is inter-
106 cepted and sent to the wxWindows class. If not, all input to the widget
107 that gets pointed to by m_widget gets intercepted and sent to the class.
111 //-----------------------------------------------------------------------------
113 //-----------------------------------------------------------------------------
115 extern wxList wxPendingDelete
;
116 extern wxList wxTopLevelWindows
;
117 extern bool g_blockEventsOnDrag
;
119 //-----------------------------------------------------------------------------
120 // "expose_event" (of m_wxwindow, not of m_widget)
121 //-----------------------------------------------------------------------------
123 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
125 if (!win
->HasVMT()) return;
126 if (g_blockEventsOnDrag
) return;
128 win
->m_updateRegion
.Union( gdk_event
->area
.x
,
130 gdk_event
->area
.width
,
131 gdk_event
->area
.height
);
133 if (gdk_event
->count
> 0) return;
135 wxPaintEvent
event( win
->GetId() );
136 event
.SetEventObject( win
);
137 win
->GetEventHandler()->ProcessEvent( event
);
139 win
->m_updateRegion
.Clear();
142 //-----------------------------------------------------------------------------
143 // "draw" (of m_wxwindow, not of m_widget)
144 //-----------------------------------------------------------------------------
146 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
148 if (!win
->HasVMT()) return;
149 if (g_blockEventsOnDrag
) return;
151 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
153 wxPaintEvent
event( win
->GetId() );
154 event
.SetEventObject( win
);
155 win
->GetEventHandler()->ProcessEvent( event
);
157 win
->m_updateRegion
.Clear();
160 //-----------------------------------------------------------------------------
162 //-----------------------------------------------------------------------------
164 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
166 if (!win
->HasVMT()) return FALSE
;
167 if (g_blockEventsOnDrag
) return FALSE
;
170 printf( "OnKeyPress from " );
171 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
172 printf( win->GetClassInfo()->GetClassName() );
177 switch (gdk_event
->keyval
)
179 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
180 case GDK_Tab
: key_code
= WXK_TAB
; break;
181 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
182 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
183 case GDK_Return
: key_code
= WXK_RETURN
; break;
184 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
185 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
186 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
187 case GDK_Delete
: key_code
= WXK_DELETE
; break;
188 case GDK_Home
: key_code
= WXK_HOME
; break;
189 case GDK_Left
: key_code
= WXK_LEFT
; break;
190 case GDK_Up
: key_code
= WXK_UP
; break;
191 case GDK_Right
: key_code
= WXK_RIGHT
; break;
192 case GDK_Down
: key_code
= WXK_DOWN
; break;
193 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
194 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
195 case GDK_Next
: key_code
= WXK_NEXT
; break;
196 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
197 case GDK_End
: key_code
= WXK_END
; break;
198 case GDK_Begin
: key_code
= WXK_HOME
; break;
199 case GDK_Select
: key_code
= WXK_SELECT
; break;
200 case GDK_Print
: key_code
= WXK_PRINT
; break;
201 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
202 case GDK_Insert
: key_code
= WXK_INSERT
; break;
203 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
204 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
205 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
206 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
207 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
208 case GDK_KP_Up
: key_code
= WXK_UP
; break;
209 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
210 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
211 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
212 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
213 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
214 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
215 case GDK_KP_End
: key_code
= WXK_END
; break;
216 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
217 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
218 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
219 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
220 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
221 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
222 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
223 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
224 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
225 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
226 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
227 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
228 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
229 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
230 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
231 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
232 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
233 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
234 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
235 case GDK_F1
: key_code
= WXK_F1
; break;
236 case GDK_F2
: key_code
= WXK_F2
; break;
237 case GDK_F3
: key_code
= WXK_F3
; break;
238 case GDK_F4
: key_code
= WXK_F4
; break;
239 case GDK_F5
: key_code
= WXK_F5
; break;
240 case GDK_F6
: key_code
= WXK_F6
; break;
241 case GDK_F7
: key_code
= WXK_F7
; break;
242 case GDK_F8
: key_code
= WXK_F8
; break;
243 case GDK_F9
: key_code
= WXK_F9
; break;
244 case GDK_F10
: key_code
= WXK_F10
; break;
245 case GDK_F11
: key_code
= WXK_F11
; break;
246 case GDK_F12
: key_code
= WXK_F12
; break;
249 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
250 key_code
= gdk_event
->keyval
;
254 if (!key_code
) return FALSE
;
256 wxKeyEvent
event( wxEVT_CHAR
);
257 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
258 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
259 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
260 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
261 event
.m_keyCode
= key_code
;
264 event
.SetEventObject( win
);
266 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
270 wxWindow
*ancestor
= win
;
273 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
276 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
277 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
280 ancestor
= ancestor
->GetParent();
286 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
287 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
293 //-----------------------------------------------------------------------------
294 // "button_press_event"
295 //-----------------------------------------------------------------------------
297 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
299 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
301 if (g_blockEventsOnDrag
) return TRUE
;
305 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
307 gtk_widget_grab_focus (win
->m_wxwindow
);
310 printf( "GrabFocus from " );
311 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
312 printf( win->GetClassInfo()->GetClassName() );
319 if (!win
->HasVMT()) return TRUE
;
322 printf( "OnButtonPress from " );
323 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
324 printf( win->GetClassInfo()->GetClassName() );
328 wxEventType event_type
= wxEVT_LEFT_DOWN
;
330 if (gdk_event
->button
== 1)
332 switch (gdk_event
->type
)
334 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
335 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
339 else if (gdk_event
->button
== 2)
341 switch (gdk_event
->type
)
343 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
344 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
348 else if (gdk_event
->button
== 3)
350 switch (gdk_event
->type
)
352 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
353 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
358 wxMouseEvent
event( event_type
);
359 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
360 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
361 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
362 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
363 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
364 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
365 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
367 event
.m_x
= (long)gdk_event
->x
;
368 event
.m_y
= (long)gdk_event
->y
;
370 // Some control don't have their own X window and thus cannot get
373 wxNode
*node
= win
->GetChildren()->First();
376 wxWindow
*child
= (wxWindow
*)node
->Data();
377 if ((child
->m_x
<= event
.m_x
) &&
378 (child
->m_y
<= event
.m_y
) &&
379 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
380 (child
->m_y
+child
->m_height
>= event
.m_y
))
383 event
.m_x
-= child
->m_x
;
384 event
.m_y
-= child
->m_y
;
390 event
.SetEventObject( win
);
392 if (win
->GetEventHandler()->ProcessEvent( event
))
393 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
398 //-----------------------------------------------------------------------------
399 // "button_release_event"
400 //-----------------------------------------------------------------------------
402 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
404 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
405 if (g_blockEventsOnDrag
) return TRUE
;
407 if (!win
->HasVMT()) return TRUE
;
410 printf( "OnButtonRelease from " );
411 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
412 printf( win->GetClassInfo()->GetClassName() );
416 wxEventType event_type
= wxEVT_NULL
;
418 switch (gdk_event
->button
)
420 case 1: event_type
= wxEVT_LEFT_UP
; break;
421 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
422 case 3: event_type
= wxEVT_RIGHT_UP
; break;
425 wxMouseEvent
event( event_type
);
426 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
427 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
428 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
429 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
430 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
431 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
432 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
433 event
.m_x
= (long)gdk_event
->x
;
434 event
.m_y
= (long)gdk_event
->y
;
436 // Some control don't have their own X window and thus cannot get
439 wxNode
*node
= win
->GetChildren()->First();
442 wxWindow
*child
= (wxWindow
*)node
->Data();
443 if ((child
->m_x
<= event
.m_x
) &&
444 (child
->m_y
<= event
.m_y
) &&
445 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
446 (child
->m_y
+child
->m_height
>= event
.m_y
))
449 event
.m_x
-= child
->m_x
;
450 event
.m_y
-= child
->m_y
;
456 event
.SetEventObject( win
);
458 if (win
->GetEventHandler()->ProcessEvent( event
))
459 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
464 //-----------------------------------------------------------------------------
465 // "motion_notify_event"
466 //-----------------------------------------------------------------------------
468 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
470 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
471 if (g_blockEventsOnDrag
) return TRUE
;
473 if (!win
->HasVMT()) return TRUE
;
476 printf( "OnMotion from " );
477 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
478 printf( win->GetClassInfo()->GetClassName() );
482 wxMouseEvent
event( wxEVT_MOTION
);
483 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
484 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
485 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
486 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
487 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
488 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
489 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
491 event
.m_x
= (long)gdk_event
->x
;
492 event
.m_y
= (long)gdk_event
->y
;
494 // Some control don't have their own X window and thus cannot get
497 wxNode
*node
= win
->GetChildren()->First();
500 wxWindow
*child
= (wxWindow
*)node
->Data();
501 if ((child
->m_x
<= event
.m_x
) &&
502 (child
->m_y
<= event
.m_y
) &&
503 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
504 (child
->m_y
+child
->m_height
>= event
.m_y
))
507 event
.m_x
-= child
->m_x
;
508 event
.m_y
-= child
->m_y
;
514 event
.SetEventObject( win
);
516 if (win
->GetEventHandler()->ProcessEvent( event
))
517 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
522 //-----------------------------------------------------------------------------
524 //-----------------------------------------------------------------------------
526 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
528 if (g_blockEventsOnDrag
) return TRUE
;
531 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
533 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
535 printf( "SetFocus flag from " );
536 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
537 printf( win->GetClassInfo()->GetClassName() );
543 if (!win
->HasVMT()) return TRUE
;
546 printf( "OnSetFocus from " );
547 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
548 printf( win->GetClassInfo()->GetClassName() );
550 printf( WXSTRINGCAST win->GetLabel() );
554 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
555 event
.SetEventObject( win
);
557 if (win
->GetEventHandler()->ProcessEvent( event
))
558 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
563 //-----------------------------------------------------------------------------
565 //-----------------------------------------------------------------------------
567 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
569 if (g_blockEventsOnDrag
) return TRUE
;
572 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
573 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
576 if (!win
->HasVMT()) return TRUE
;
579 printf( "OnKillFocus from " );
580 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
581 printf( win->GetClassInfo()->GetClassName() );
585 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
586 event
.SetEventObject( win
);
588 if (win
->GetEventHandler()->ProcessEvent( event
))
589 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
594 //-----------------------------------------------------------------------------
595 // "value_changed" from m_vAdjust
596 //-----------------------------------------------------------------------------
598 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
600 if (g_blockEventsOnDrag
) return;
603 printf( "OnVScroll from " );
604 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
605 printf( win->GetClassInfo()->GetClassName() );
609 if (!win
->HasVMT()) return;
611 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
612 if (fabs(diff
) < 0.2) return;
614 wxEventType command
= wxEVT_NULL
;
616 float line_step
= win
->m_vAdjust
->step_increment
;
617 float page_step
= win
->m_vAdjust
->page_increment
;
619 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
620 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
621 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
622 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
623 else command
= wxEVT_SCROLL_THUMBTRACK
;
625 int value
= (int)(win
->m_vAdjust
->value
+0.5);
627 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
628 event
.SetEventObject( win
);
629 win
->GetEventHandler()->ProcessEvent( event
);
632 //-----------------------------------------------------------------------------
633 // "value_changed" from m_hAdjust
634 //-----------------------------------------------------------------------------
636 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
638 if (g_blockEventsOnDrag
) return;
641 printf( "OnHScroll from " );
642 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
643 printf( win->GetClassInfo()->GetClassName() );
647 if (!win
->HasVMT()) return;
649 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
650 if (fabs(diff
) < 0.2) return;
652 wxEventType command
= wxEVT_NULL
;
654 float line_step
= win
->m_hAdjust
->step_increment
;
655 float page_step
= win
->m_hAdjust
->page_increment
;
657 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
658 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
659 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
660 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
661 else command
= wxEVT_SCROLL_THUMBTRACK
;
663 int value
= (int)(win
->m_hAdjust
->value
+0.5);
665 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
666 event
.SetEventObject( win
);
667 win
->GetEventHandler()->ProcessEvent( event
);
670 //-----------------------------------------------------------------------------
671 // "changed" from m_vAdjust
672 //-----------------------------------------------------------------------------
674 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
676 if (g_blockEventsOnDrag
) return;
679 printf( "OnVScroll change from " );
680 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
681 printf( win->GetClassInfo()->GetClassName() );
685 if (!win
->HasVMT()) return;
687 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
688 int value
= (int)(win
->m_vAdjust
->value
+0.5);
690 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
691 event
.SetEventObject( win
);
692 win
->GetEventHandler()->ProcessEvent( event
);
695 //-----------------------------------------------------------------------------
696 // "changed" from m_hAdjust
697 //-----------------------------------------------------------------------------
699 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
701 if (g_blockEventsOnDrag
) return;
704 printf( "OnHScroll change from " );
705 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
706 printf( win->GetClassInfo()->GetClassName() );
710 if (!win
->HasVMT()) return;
712 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
713 int value
= (int)(win
->m_hAdjust
->value
+0.5);
715 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
716 event
.SetEventObject( win
);
717 win
->GetEventHandler()->ProcessEvent( event
);
720 //-----------------------------------------------------------------------------
721 // "drop_data_available_event"
722 //-----------------------------------------------------------------------------
724 static void gtk_window_drop_callback( GtkWidget
*widget
, GdkEvent
*event
, wxWindow
*win
)
726 if (!win
->HasVMT()) return;
728 if (win
->GetDropTarget())
732 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
733 win
->GetDropTarget()->Drop( event
, x
, y
);
737 g_free (event->dropdataavailable.data);
738 g_free (event->dropdataavailable.data_type);
742 //-----------------------------------------------------------------------------
743 // "enter_notify_event"
744 //-----------------------------------------------------------------------------
746 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
748 if (widget
->window
!= gdk_event
->window
) return TRUE
;
749 if (g_blockEventsOnDrag
) return TRUE
;
750 if (!win
->HasVMT()) return TRUE
;
753 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
755 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
756 event
.SetEventObject( win
);
757 return win
->GetEventHandler()->ProcessEvent( event
);
760 //-----------------------------------------------------------------------------
761 // "leave_notify_event"
762 //-----------------------------------------------------------------------------
764 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
766 if (widget
->window
!= gdk_event
->window
) return TRUE
;
767 if (!win
->HasVMT()) return TRUE
;
768 if (g_blockEventsOnDrag
) return TRUE
;
771 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
773 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
774 event
.SetEventObject( win
);
775 return win
->GetEventHandler()->ProcessEvent( event
);
778 //-----------------------------------------------------------------------------
780 //-----------------------------------------------------------------------------
782 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
784 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
785 EVT_SIZE(wxWindow::OnSize
)
786 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
787 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
788 EVT_IDLE(wxWindow::OnIdle
)
793 m_widget
= (GtkWidget
*) NULL
;
794 m_wxwindow
= (GtkWidget
*) NULL
;
795 m_parent
= (wxWindow
*) NULL
;
796 m_children
.DeleteContents( FALSE
);
806 m_eventHandler
= this;
807 m_windowValidator
= (wxValidator
*) NULL
;
809 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
810 m_font
= *wxSWISS_FONT
;
812 m_windowName
= "noname";
813 m_constraints
= (wxLayoutConstraints
*) NULL
;
814 m_constraintsInvolvedIn
= (wxList
*) NULL
;
815 m_windowSizer
= (wxSizer
*) NULL
;
816 m_sizerParent
= (wxWindow
*) NULL
;
817 m_autoLayout
= FALSE
;
821 m_hasScrolling
= FALSE
;
822 m_hAdjust
= (GtkAdjustment
*) NULL
;
823 m_vAdjust
= (GtkAdjustment
*) NULL
;
824 m_oldHorizontalPos
= 0.0;
825 m_oldVerticalPos
= 0.0;
828 m_pDropTarget
= (wxDropTarget
*) NULL
;
830 m_hasOwnStyle
= FALSE
;
833 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
834 const wxPoint
&pos
, const wxSize
&size
,
835 long style
, const wxString
&name
)
841 m_cursor
= (wxCursor
*) NULL
;
843 PreCreation( parent
, id
, pos
, size
, style
, name
);
845 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
846 m_hasScrolling
= TRUE
;
848 GtkScrolledWindow
*s_window
;
849 s_window
= GTK_SCROLLED_WINDOW(m_widget
);
851 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
852 scroll_class
->scrollbar_spacing
= 0;
854 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
856 m_oldHorizontalPos
= 0.0;
857 m_oldVerticalPos
= 0.0;
859 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
860 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
862 gtk_signal_connect (GTK_OBJECT (m_hAdjust
), "value_changed",
863 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
864 gtk_signal_connect (GTK_OBJECT (m_vAdjust
), "value_changed",
865 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
867 gtk_signal_connect (GTK_OBJECT (m_hAdjust
), "changed",
868 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
869 gtk_signal_connect (GTK_OBJECT (m_vAdjust
), "changed",
870 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
872 GtkViewport
*viewport
;
873 viewport
= GTK_VIEWPORT(s_window
->viewport
);
875 if (m_windowStyle
& wxRAISED_BORDER
)
877 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
879 else if (m_windowStyle
& wxSUNKEN_BORDER
)
881 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
885 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
888 m_wxwindow
= gtk_myfixed_new();
890 if (m_wxwindow
) GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
892 if (m_windowStyle
& wxTAB_TRAVERSAL
== wxTAB_TRAVERSAL
)
893 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
895 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
897 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
899 // shut the viewport up
900 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
901 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
903 // I _really_ don't want scrollbars in the beginning
904 m_vAdjust
->lower
= 0.0;
905 m_vAdjust
->upper
= 1.0;
906 m_vAdjust
->value
= 0.0;
907 m_vAdjust
->step_increment
= 1.0;
908 m_vAdjust
->page_increment
= 1.0;
909 m_vAdjust
->page_size
= 5.0;
910 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
911 m_hAdjust
->lower
= 0.0;
912 m_hAdjust
->upper
= 1.0;
913 m_hAdjust
->value
= 0.0;
914 m_hAdjust
->step_increment
= 1.0;
915 m_hAdjust
->page_increment
= 1.0;
916 m_hAdjust
->page_size
= 5.0;
917 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
919 gtk_widget_show( m_wxwindow
);
928 wxWindow::~wxWindow(void)
932 if (m_pDropTarget
) delete m_pDropTarget
;
934 if (m_parent
) m_parent
->RemoveChild( this );
935 if (m_widget
) Show( FALSE
);
939 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
941 if (m_widget
) gtk_widget_destroy( m_widget
);
945 DeleteRelatedConstraints();
948 // This removes any dangling pointers to this window
949 // in other windows' constraintsInvolvedIn lists.
950 UnsetConstraints(m_constraints
);
951 delete m_constraints
;
952 m_constraints
= (wxLayoutConstraints
*) NULL
;
956 delete m_windowSizer
;
957 m_windowSizer
= (wxSizer
*) NULL
;
959 // If this is a child of a sizer, remove self from parent
960 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
962 // Just in case the window has been Closed, but
963 // we're then deleting immediately: don't leave
964 // dangling pointers.
965 wxPendingDelete
.DeleteObject(this);
967 // Just in case we've loaded a top-level window via
968 // wxWindow::LoadNativeDialog but we weren't a dialog
970 wxTopLevelWindows
.DeleteObject(this);
972 if (m_windowValidator
) delete m_windowValidator
;
975 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
976 const wxPoint
&pos
, const wxSize
&size
,
977 long style
, const wxString
&name
)
979 if (m_needParent
&& (parent
== NULL
))
980 wxFatalError( "Need complete parent.", name
);
982 m_widget
= (GtkWidget
*) NULL
;
985 m_children
.DeleteContents( FALSE
);
989 if (m_width
== -1) m_width
= 20;
991 if (m_height
== -1) m_height
= 20;
997 m_eventHandler
= this;
1000 if (m_cursor
== NULL
)
1001 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1002 m_font
= *wxSWISS_FONT
;
1003 m_backgroundColour
= wxWHITE
;
1004 m_foregroundColour
= wxBLACK
;
1005 m_windowStyle
= style
;
1006 m_windowName
= name
;
1007 m_constraints
= (wxLayoutConstraints
*) NULL
;
1008 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1009 m_windowSizer
= (wxSizer
*) NULL
;
1010 m_sizerParent
= (wxWindow
*) NULL
;
1011 m_autoLayout
= FALSE
;
1012 m_pDropTarget
= (wxDropTarget
*) NULL
;
1014 m_windowValidator
= (wxValidator
*) NULL
;
1015 m_hasOwnStyle
= FALSE
;
1018 void wxWindow::PostCreation(void)
1020 if (m_parent
) m_parent
->AddChild( this );
1022 // GtkStyle *style = m_widget->style;
1023 // style->font = m_font.GetInternalFont( 1.0 ); // destroy old font ?
1025 GtkWidget
*connect_widget
= GetConnectWidget();
1029 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1030 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1032 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1033 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1036 gtk_signal_connect( GTK_OBJECT(connect_widget
), "key_press_event",
1037 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1039 gtk_signal_connect( GTK_OBJECT(connect_widget
), "button_press_event",
1040 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1042 gtk_signal_connect( GTK_OBJECT(connect_widget
), "button_release_event",
1043 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1045 gtk_signal_connect( GTK_OBJECT(connect_widget
), "motion_notify_event",
1046 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1048 gtk_signal_connect( GTK_OBJECT(connect_widget
), "focus_in_event",
1049 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1051 gtk_signal_connect( GTK_OBJECT(connect_widget
), "focus_out_event",
1052 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1054 // Only for cursor handling
1056 gtk_signal_connect( GTK_OBJECT(m_widget
), "enter_notify_event",
1057 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1059 gtk_signal_connect( GTK_OBJECT(m_widget
), "leave_notify_event",
1060 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1064 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "enter_notify_event",
1065 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1067 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "leave_notify_event",
1068 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1071 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1075 gtk_widget_realize( m_wxwindow
);
1076 gdk_gc_set_exposures( m_wxwindow
->style
->fg_gc
[0], TRUE
);
1079 SetCursor( wxSTANDARD_CURSOR
);
1084 bool wxWindow::HasVMT(void)
1089 bool wxWindow::Close( bool force
)
1091 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1092 event
.SetEventObject(this);
1093 event
.SetForce(force
);
1095 return GetEventHandler()->ProcessEvent(event
);
1098 bool wxWindow::Destroy(void)
1105 bool wxWindow::DestroyChildren(void)
1110 while ((node
= GetChildren()->First()) != (wxNode
*)NULL
)
1113 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1116 if (GetChildren()->Member(child
)) delete node
;
1123 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1125 // are we to set fonts here ?
1128 void wxWindow::ImplementSetSize(void)
1130 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1131 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1132 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_minWidth
;
1133 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_minHeight
;
1134 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1137 void wxWindow::ImplementSetPosition(void)
1139 if (IS_KIND_OF(this,wxFrame
) || IS_KIND_OF(this,wxDialog
))
1141 if ((m_x
!= -1) || (m_y
!= -1))
1142 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
1148 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1152 if ((m_parent
) && (m_parent
->m_wxwindow
))
1153 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
, m_y
);
1155 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1158 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1160 if (m_resizing
) return; // I don't like recursions
1168 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1170 if (newX
== -1) newX
= m_x
;
1171 if (newY
== -1) newY
= m_y
;
1172 if (newW
== -1) newW
= m_width
;
1173 if (newH
== -1) newH
= m_height
;
1176 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1178 if (newW
== -1) newW
= 80;
1181 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1183 if (newH
== -1) newH
= 26;
1186 if ((m_x
!= newX
) || (m_y
!= newY
) || (!m_sizeSet
))
1190 ImplementSetPosition();
1192 if ((m_width
!= newW
) || (m_height
!= newH
) || (!m_sizeSet
))
1200 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1201 event
.SetEventObject( this );
1202 ProcessEvent( event
);
1207 void wxWindow::SetSize( int width
, int height
)
1209 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1212 void wxWindow::Move( int x
, int y
)
1214 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1217 void wxWindow::GetSize( int *width
, int *height
) const
1219 if (width
) (*width
) = m_width
;
1220 if (height
) (*height
) = m_height
;
1223 void wxWindow::SetClientSize( int width
, int height
)
1227 SetSize( width
, height
);
1234 if (!m_hasScrolling
)
1237 do we have sunken dialogs ?
1239 GtkStyleClass *window_class = m_wxwindow->style->klass;
1241 dw += 2 * window_class->xthickness;
1242 dh += 2 * window_class->ythickness;
1247 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1248 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1250 GtkWidget
*viewport
= scroll_window
->viewport
;
1251 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1253 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1254 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1256 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1257 (m_windowStyle
& wxSUNKEN_BORDER
))
1259 dw
+= 2 * viewport_class
->xthickness
;
1260 dh
+= 2 * viewport_class
->ythickness
;
1263 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1265 dw
+= vscrollbar
->allocation
.width
;
1266 dw
+= scroll_class
->scrollbar_spacing
;
1269 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1271 dh
+= hscrollbar
->allocation
.height
;
1272 dw
+= scroll_class
->scrollbar_spacing
;
1276 SetSize( width
+dw
, height
+dh
);
1280 void wxWindow::GetClientSize( int *width
, int *height
) const
1284 if (width
) (*width
) = m_width
;
1285 if (height
) (*height
) = m_height
;
1292 if (!m_hasScrolling
)
1295 do we have sunken dialogs ?
1297 GtkStyleClass *window_class = m_wxwindow->style->klass;
1299 dw += 2 * window_class->xthickness;
1300 dh += 2 * window_class->ythickness;
1305 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1306 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1308 GtkWidget
*viewport
= scroll_window
->viewport
;
1309 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1311 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1312 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1314 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1315 (m_windowStyle
& wxSUNKEN_BORDER
))
1317 dw
+= 2 * viewport_class
->xthickness
;
1318 dh
+= 2 * viewport_class
->ythickness
;
1321 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1323 // dw += vscrollbar->allocation.width;
1324 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1325 dw
+= scroll_class
->scrollbar_spacing
;
1328 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1330 // dh += hscrollbar->allocation.height;
1332 dh
+= scroll_class
->scrollbar_spacing
;
1336 if (width
) (*width
) = m_width
- dw
;
1337 if (height
) (*height
) = m_height
- dh
;
1341 void wxWindow::GetPosition( int *x
, int *y
) const
1347 void wxWindow::ClientToScreen( int *x
, int *y
)
1349 GdkWindow
*source
= (GdkWindow
*) NULL
;
1351 source
= m_wxwindow
->window
;
1353 source
= m_widget
->window
;
1357 gdk_window_get_origin( source
, &org_x
, &org_y
);
1361 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1363 org_x
+= m_widget
->allocation
.x
;
1364 org_y
+= m_widget
->allocation
.y
;
1372 void wxWindow::ScreenToClient( int *x
, int *y
)
1374 GdkWindow
*source
= (GdkWindow
*) NULL
;
1376 source
= m_wxwindow
->window
;
1378 source
= m_widget
->window
;
1382 gdk_window_get_origin( source
, &org_x
, &org_y
);
1386 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1388 org_x
+= m_widget
->allocation
.x
;
1389 org_y
+= m_widget
->allocation
.y
;
1397 void wxWindow::Centre( int direction
)
1399 if (IS_KIND_OF(this,wxDialog
) || IS_KIND_OF(this,wxFrame
))
1401 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (gdk_screen_width () - m_width
) / 2;
1402 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (gdk_screen_height () - m_height
) / 2;
1403 ImplementSetPosition();
1411 m_parent
->GetSize( &p_w
, &p_h
);
1412 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (p_w
- m_width
) / 2;
1413 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (p_h
- m_height
) / 2;
1414 ImplementSetPosition();
1419 void wxWindow::Fit(void)
1423 wxNode
*node
= GetChildren()->First();
1426 wxWindow
*win
= (wxWindow
*)node
->Data();
1428 win
->GetPosition(&wx
, &wy
);
1429 win
->GetSize(&ww
, &wh
);
1430 if ( wx
+ ww
> maxX
)
1432 if ( wy
+ wh
> maxY
)
1435 node
= node
->Next();
1437 SetClientSize(maxX
+ 5, maxY
+ 10);
1440 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1448 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1450 //if (GetAutoLayout()) Layout();
1453 bool wxWindow::Show( bool show
)
1456 gtk_widget_show( m_widget
);
1458 gtk_widget_hide( m_widget
);
1463 void wxWindow::Enable( bool enable
)
1465 m_isEnabled
= enable
;
1466 gtk_widget_set_sensitive( m_widget
, enable
);
1467 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1470 int wxWindow::GetCharHeight(void) const
1472 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1473 return font
->ascent
+ font
->descent
;
1476 int wxWindow::GetCharWidth(void) const
1478 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1479 return gdk_string_width( font
, "H" );
1482 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1483 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1485 wxFont fontToUse
= m_font
;
1486 if (theFont
) fontToUse
= *theFont
;
1488 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1489 if (x
) (*x
) = gdk_string_width( font
, string
);
1490 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1491 if (descent
) (*descent
) = font
->descent
;
1492 if (externalLeading
) (*externalLeading
) = 0; // ??
1495 void wxWindow::MakeModal( bool modal
)
1498 // Disable all other windows
1499 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1501 wxNode
*node
= wxTopLevelWindows
.First();
1504 wxWindow
*win
= (wxWindow
*)node
->Data();
1506 win
->Enable(!modal
);
1508 node
= node
->Next();
1513 void wxWindow::SetFocus(void)
1515 GtkWidget
*connect_widget
= GetConnectWidget();
1518 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) && !GTK_WIDGET_HAS_FOCUS (connect_widget
) )
1520 gtk_widget_grab_focus (connect_widget
);
1525 bool wxWindow::OnClose(void)
1530 void wxWindow::AddChild( wxWindow
*child
)
1532 // Addchild is (often) called before the program
1533 // has left the parents constructor so that no
1534 // virtual tables work yet. The approach below
1535 // practically imitates virtual tables, i.e. it
1536 // implements a different AddChild() behaviour
1537 // for wxFrame, wxDialog, wxWindow and
1538 // wxMDIParentFrame.
1540 // wxFrame and wxDialog as children aren't placed into the parents
1542 if (( IS_KIND_OF(child
,wxFrame
) || IS_KIND_OF(child
,wxDialog
) ) &&
1543 (!IS_KIND_OF(child
,wxMDIChildFrame
)))
1545 m_children
.Append( child
);
1547 if ((child
->m_x
!= -1) && (child
->m_y
!= -1))
1548 gtk_widget_set_uposition( child
->m_widget
, child
->m_x
, child
->m_y
);
1553 // In the case of an wxMDIChildFrame descendant, we use the
1554 // client windows's AddChild()
1556 if (IS_KIND_OF(this,wxMDIParentFrame
))
1558 if (IS_KIND_OF(child
,wxMDIChildFrame
))
1560 wxMDIClientWindow
*client
= ((wxMDIParentFrame
*)this)->GetClientWindow();
1563 client
->AddChild( child
);
1569 // wxNotebook is very special, so it has a private AddChild()
1571 if (IS_KIND_OF(this,wxNotebook
))
1573 wxNotebook
*tab
= (wxNotebook
*)this;
1574 tab
->AddChild( child
);
1578 // wxFrame has a private AddChild
1580 if (IS_KIND_OF(this,wxFrame
) && !IS_KIND_OF(this,wxMDIChildFrame
))
1582 wxFrame
*frame
= (wxFrame
*)this;
1583 frame
->AddChild( child
);
1589 m_children
.Append( child
);
1590 if (m_wxwindow
) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), child
->m_widget
,
1591 child
->m_x
, child
->m_y
);
1593 gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height
);
1596 wxList
*wxWindow::GetChildren(void)
1598 return (&m_children
);
1601 void wxWindow::RemoveChild( wxWindow
*child
)
1604 GetChildren()->DeleteObject( child
);
1605 child
->m_parent
= (wxWindow
*) NULL
;
1608 void wxWindow::SetReturnCode( int retCode
)
1610 m_retCode
= retCode
;
1613 int wxWindow::GetReturnCode(void)
1618 void wxWindow::Raise(void)
1620 if (m_widget
) gdk_window_raise( m_widget
->window
);
1623 void wxWindow::Lower(void)
1625 if (m_widget
) gdk_window_lower( m_widget
->window
);
1628 wxEvtHandler
*wxWindow::GetEventHandler(void)
1630 return m_eventHandler
;
1633 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
1635 m_eventHandler
= handler
;
1638 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
1640 handler
->SetNextHandler(GetEventHandler());
1641 SetEventHandler(handler
);
1644 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
1646 if ( GetEventHandler() )
1648 wxEvtHandler
*handlerA
= GetEventHandler();
1649 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
1650 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
1651 SetEventHandler(handlerB
);
1652 if ( deleteHandler
)
1655 return (wxEvtHandler
*) NULL
;
1661 return (wxEvtHandler
*) NULL
;
1664 wxValidator
*wxWindow::GetValidator(void)
1666 return m_windowValidator
;
1669 void wxWindow::SetValidator( const wxValidator
& validator
)
1671 if (m_windowValidator
) delete m_windowValidator
;
1672 m_windowValidator
= validator
.Clone();
1673 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
1676 bool wxWindow::IsBeingDeleted(void)
1681 void wxWindow::SetId( wxWindowID id
)
1686 wxWindowID
wxWindow::GetId(void)
1691 void wxWindow::SetCursor( const wxCursor
&cursor
)
1693 wxASSERT(m_cursor
!= NULL
);
1695 if (m_cursor
!= NULL
)
1696 if (*m_cursor
== cursor
)
1698 (*m_cursor
) = cursor
;
1699 if (m_widget
->window
)
1700 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
1701 if (m_wxwindow
&& m_wxwindow
->window
)
1702 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
1705 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
1707 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
1710 gdk_window_clear_area( m_wxwindow
->window
,
1724 GetClientSize( &w
, &h
);
1726 GdkRectangle gdk_rect
;
1730 gdk_rect
.height
= h
;
1731 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1736 GdkRectangle gdk_rect
;
1737 gdk_rect
.x
= rect
->x
;
1738 gdk_rect
.y
= rect
->y
;
1739 gdk_rect
.width
= rect
->width
;
1740 gdk_rect
.height
= rect
->height
;
1743 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1745 gtk_widget_draw( m_widget
, &gdk_rect
);
1749 wxRegion
wxWindow::GetUpdateRegion() const
1751 return m_updateRegion
;
1754 bool wxWindow::IsExposed( int x
, int y
) const
1756 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
1759 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
1761 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
1764 bool wxWindow::IsExposed( const wxPoint
& pt
) const
1766 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
1769 bool wxWindow::IsExposed( const wxRect
& rect
) const
1771 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
1774 void wxWindow::Clear(void)
1776 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
1779 wxColour
wxWindow::GetBackgroundColour(void) const
1781 return m_backgroundColour
;
1784 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
1786 m_backgroundColour
= colour
;
1789 m_backgroundColour
.CalcPixel( m_wxwindow
->style
->colormap
);
1790 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
1791 gdk_window_clear( m_wxwindow
->window
);
1796 wxColour
wxWindow::GetForegroundColour(void) const
1798 return m_foregroundColour
;
1801 void wxWindow::SetForegroundColour( const wxColour
&colour
)
1803 m_foregroundColour
= colour
;
1806 bool wxWindow::Validate(void)
1808 wxNode
*node
= GetChildren()->First();
1811 wxWindow
*child
= (wxWindow
*)node
->Data();
1812 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
1814 node
= node
->Next();
1819 bool wxWindow::TransferDataToWindow(void)
1821 wxNode
*node
= GetChildren()->First();
1824 wxWindow
*child
= (wxWindow
*)node
->Data();
1825 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
1826 !child
->GetValidator()->TransferToWindow() )
1828 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
1831 node
= node
->Next();
1836 bool wxWindow::TransferDataFromWindow(void)
1838 wxNode
*node
= GetChildren()->First();
1841 wxWindow
*child
= (wxWindow
*)node
->Data();
1842 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
1844 node
= node
->Next();
1849 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
1851 m_acceleratorTable
= accel
;
1854 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
1856 TransferDataToWindow();
1859 void wxWindow::InitDialog(void)
1861 wxInitDialogEvent
event(GetId());
1862 event
.SetEventObject( this );
1863 GetEventHandler()->ProcessEvent(event
);
1866 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
1868 menu
->SetInvokingWindow( win
);
1869 wxNode
*node
= menu
->m_items
.First();
1872 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
1873 if (menuitem
->IsSubMenu())
1874 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
1875 node
= node
->Next();
1879 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
1881 SetInvokingWindow( menu
, this );
1882 gtk_menu_popup( GTK_MENU(menu
->m_menu
), (GtkWidget
*) NULL
, (GtkWidget
*) NULL
, (GtkMenuPositionFunc
) NULL
, NULL
, 0, 0 );
1886 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
1888 GtkWidget
*dnd_widget
= GetConnectWidget();
1892 gtk_signal_disconnect_by_func( GTK_OBJECT(dnd_widget
),
1893 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
1895 m_pDropTarget
->UnregisterWidget( dnd_widget
);
1896 delete m_pDropTarget
;
1898 m_pDropTarget
= dropTarget
;
1901 m_pDropTarget
->RegisterWidget( dnd_widget
);
1903 gtk_signal_connect( GTK_OBJECT(dnd_widget
), "drop_data_available_event",
1904 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
1908 wxDropTarget
*wxWindow::GetDropTarget() const
1910 return m_pDropTarget
;
1913 GtkWidget
* wxWindow::GetConnectWidget(void)
1915 GtkWidget
*connect_widget
= m_widget
;
1916 if (m_wxwindow
) connect_widget
= m_wxwindow
;
1918 return connect_widget
;
1921 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
1923 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
1924 return (window
== m_widget
->window
);
1927 void wxWindow::SetFont( const wxFont
&font
)
1929 if (((wxFont
*)&font
)->Ok())
1932 m_font
= *wxSWISS_FONT
;
1934 GtkStyle
*style
= (GtkStyle
*) NULL
;
1937 m_hasOwnStyle
= TRUE
;
1938 style
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
1942 style
= gtk_widget_get_style( m_widget
);
1945 gdk_font_unref( style
->font
);
1946 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
1948 gtk_widget_set_style( m_widget
, style
);
1951 wxFont
*wxWindow::GetFont(void)
1956 void wxWindow::SetWindowStyleFlag( long flag
)
1958 m_windowStyle
= flag
;
1961 long wxWindow::GetWindowStyleFlag(void) const
1963 return m_windowStyle
;
1966 void wxWindow::CaptureMouse(void)
1968 GtkWidget
*connect_widget
= GetConnectWidget();
1969 gtk_grab_add( connect_widget
);
1970 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
1972 (GDK_BUTTON_PRESS_MASK
|
1973 GDK_BUTTON_RELEASE_MASK
|
1974 GDK_POINTER_MOTION_MASK
),
1975 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
1978 void wxWindow::ReleaseMouse(void)
1980 GtkWidget
*connect_widget
= GetConnectWidget();
1981 gtk_grab_remove( connect_widget
);
1982 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
1985 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
1989 wxString
wxWindow::GetTitle(void) const
1991 return (wxString
&)m_windowName
;
1994 wxString
wxWindow::GetLabel(void) const
1999 void wxWindow::SetName( const wxString
&name
)
2001 m_windowName
= name
;
2004 wxString
wxWindow::GetName(void) const
2006 return (wxString
&)m_windowName
;
2009 bool wxWindow::IsShown(void) const
2014 bool wxWindow::IsRetained(void)
2019 wxWindow
*wxWindow::FindWindow( long id
)
2021 if (id
== m_windowId
) return this;
2022 wxNode
*node
= m_children
.First();
2025 wxWindow
*child
= (wxWindow
*)node
->Data();
2026 wxWindow
*res
= child
->FindWindow( id
);
2027 if (res
) return res
;
2028 node
= node
->Next();
2030 return (wxWindow
*) NULL
;
2033 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2035 if (name
== m_windowName
) return this;
2036 wxNode
*node
= m_children
.First();
2039 wxWindow
*child
= (wxWindow
*)node
->Data();
2040 wxWindow
*res
= child
->FindWindow( name
);
2041 if (res
) return res
;
2042 node
= node
->Next();
2044 return (wxWindow
*) NULL
;
2047 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2048 int range
, bool WXUNUSED(refresh
) )
2050 if (!m_wxwindow
) return;
2052 if (orient
== wxHORIZONTAL
)
2054 float fpos
= (float)pos
;
2055 m_oldHorizontalPos
= fpos
;
2056 float frange
= (float)range
;
2057 float fthumb
= (float)thumbVisible
;
2059 if ((fabs(fpos
-m_hAdjust
->value
) < 0.2) &&
2060 (fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2061 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2064 m_hAdjust
->lower
= 0.0;
2065 m_hAdjust
->upper
= frange
;
2066 m_hAdjust
->value
= fpos
;
2067 m_hAdjust
->step_increment
= 1.0;
2068 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2069 m_hAdjust
->page_size
= fthumb
;
2073 float fpos
= (float)pos
;
2074 m_oldVerticalPos
= fpos
;
2075 float frange
= (float)range
;
2076 float fthumb
= (float)thumbVisible
;
2078 if ((fabs(fpos
-m_vAdjust
->value
) < 0.2) &&
2079 (fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2080 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2083 m_vAdjust
->lower
= 0.0;
2084 m_vAdjust
->upper
= frange
;
2085 m_vAdjust
->value
= fpos
;
2086 m_vAdjust
->step_increment
= 1.0;
2087 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
-2,0));
2088 m_vAdjust
->page_size
= fthumb
;
2091 if (m_wxwindow
->window
)
2093 if (orient
== wxHORIZONTAL
)
2094 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2096 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2098 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2102 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2104 if (!m_wxwindow
) return;
2106 if (orient
== wxHORIZONTAL
)
2108 float fpos
= (float)pos
;
2109 m_oldHorizontalPos
= fpos
;
2111 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2112 m_hAdjust
->value
= fpos
;
2116 float fpos
= (float)pos
;
2117 m_oldVerticalPos
= fpos
;
2118 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2119 m_vAdjust
->value
= fpos
;
2122 if (m_wxwindow
->window
)
2124 if (orient
== wxHORIZONTAL
)
2125 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2127 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2131 int wxWindow::GetScrollThumb( int orient
) const
2133 if (!m_wxwindow
) return 0;
2135 if (orient
== wxHORIZONTAL
)
2136 return (int)(m_hAdjust
->page_size
+0.5);
2138 return (int)(m_vAdjust
->page_size
+0.5);
2141 int wxWindow::GetScrollPos( int orient
) const
2143 if (!m_wxwindow
) return 0;
2145 if (orient
== wxHORIZONTAL
)
2146 return (int)(m_hAdjust
->value
+0.5);
2148 return (int)(m_vAdjust
->value
+0.5);
2151 int wxWindow::GetScrollRange( int orient
) const
2153 if (!m_wxwindow
) return 0;
2155 if (orient
== wxHORIZONTAL
)
2156 return (int)(m_hAdjust
->upper
+0.5);
2158 return (int)(m_vAdjust
->upper
+0.5);
2161 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2163 if (!m_wxwindow
) return;
2166 bool refresh = FALSE;
2168 if ((m_drawingOffsetX == 0) && (m_drawingOffsetY == 0))
2170 m_drawingOffsetX = -16000;
2171 m_drawingOffsetY = -16000;
2176 m_drawingOffsetX += dx;
2177 m_drawingOffsetY += dy;
2180 // printf( "X: %d Y: %d \n", (int)m_drawingOffsetX, (int)m_drawingOffsetY );
2182 gtk_myfixed_set_offset( GTK_MYFIXED(m_wxwindow), m_drawingOffsetX, m_drawingOffsetY );
2184 if (refresh) Refresh();
2186 The code here is very nifty, but it doesn't work with
2187 overlapping windows...
2192 GetClientSize( &cw
, &ch
);
2194 int w
= cw
- abs(dx
);
2195 int h
= ch
- abs(dy
);
2196 if ((h
< 0) || (w
< 0))
2203 if (dx
< 0) s_x
= -dx
;
2204 if (dy
< 0) s_y
= -dy
;
2207 if (dx
> 0) d_x
= dx
;
2208 if (dy
> 0) d_y
= dy
;
2209 gdk_window_copy_area( m_wxwindow
->window
, m_wxwindow
->style
->fg_gc
[0], d_x
, d_y
,
2210 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2213 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2214 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2215 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2216 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2218 Refresh( TRUE
, &rect
);
2221 //-------------------------------------------------------------------------------------
2223 //-------------------------------------------------------------------------------------
2225 wxLayoutConstraints
*wxWindow::GetConstraints(void) const
2227 return m_constraints
;
2230 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2234 UnsetConstraints(m_constraints
);
2235 delete m_constraints
;
2237 m_constraints
= constraints
;
2240 // Make sure other windows know they're part of a 'meaningful relationship'
2241 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2242 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2243 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2244 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2245 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2246 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2247 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2248 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2249 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2250 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2251 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2252 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2253 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2254 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2255 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2256 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2262 void wxWindow::SetAutoLayout( bool autoLayout
)
2264 m_autoLayout
= autoLayout
;
2267 bool wxWindow::GetAutoLayout(void) const
2269 return m_autoLayout
;
2272 wxSizer
*wxWindow::GetSizer(void) const
2274 return m_windowSizer
;
2277 void wxWindow::SetSizerParent( wxWindow
*win
)
2279 m_sizerParent
= win
;
2282 wxWindow
*wxWindow::GetSizerParent(void) const
2284 return m_sizerParent
;
2287 // This removes any dangling pointers to this window
2288 // in other windows' constraintsInvolvedIn lists.
2289 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2293 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2294 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2295 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2296 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2297 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2298 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2299 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2300 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2301 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2302 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2303 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2304 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2305 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2306 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2307 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2308 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2312 // Back-pointer to other windows we're involved with, so if we delete
2313 // this window, we must delete any constraints we're involved with.
2314 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2316 if (!m_constraintsInvolvedIn
)
2317 m_constraintsInvolvedIn
= new wxList
;
2318 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2319 m_constraintsInvolvedIn
->Append(otherWin
);
2322 // REMOVE back-pointer to other windows we're involved with.
2323 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2325 if (m_constraintsInvolvedIn
)
2326 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2329 // Reset any constraints that mention this window
2330 void wxWindow::DeleteRelatedConstraints(void)
2332 if (m_constraintsInvolvedIn
)
2334 wxNode
*node
= m_constraintsInvolvedIn
->First();
2337 wxWindow
*win
= (wxWindow
*)node
->Data();
2338 wxNode
*next
= node
->Next();
2339 wxLayoutConstraints
*constr
= win
->GetConstraints();
2341 // Reset any constraints involving this window
2344 constr
->left
.ResetIfWin((wxWindow
*)this);
2345 constr
->top
.ResetIfWin((wxWindow
*)this);
2346 constr
->right
.ResetIfWin((wxWindow
*)this);
2347 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2348 constr
->width
.ResetIfWin((wxWindow
*)this);
2349 constr
->height
.ResetIfWin((wxWindow
*)this);
2350 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2351 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2356 delete m_constraintsInvolvedIn
;
2357 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2361 void wxWindow::SetSizer(wxSizer
*sizer
)
2363 m_windowSizer
= sizer
;
2365 sizer
->SetSizerParent((wxWindow
*)this);
2372 bool wxWindow::Layout(void)
2374 if (GetConstraints())
2377 GetClientSize(&w
, &h
);
2378 GetConstraints()->width
.SetValue(w
);
2379 GetConstraints()->height
.SetValue(h
);
2382 // If top level (one sizer), evaluate the sizer's constraints.
2386 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2387 GetSizer()->LayoutPhase1(&noChanges
);
2388 GetSizer()->LayoutPhase2(&noChanges
);
2389 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2394 // Otherwise, evaluate child constraints
2395 ResetConstraints(); // Mark all constraints as unevaluated
2396 DoPhase(1); // Just one phase need if no sizers involved
2398 SetConstraintSizes(); // Recursively set the real window sizes
2404 // Do a phase of evaluating constraints:
2405 // the default behaviour. wxSizers may do a similar
2406 // thing, but also impose their own 'constraints'
2407 // and order the evaluation differently.
2408 bool wxWindow::LayoutPhase1(int *noChanges
)
2410 wxLayoutConstraints
*constr
= GetConstraints();
2413 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2419 bool wxWindow::LayoutPhase2(int *noChanges
)
2429 // Do a phase of evaluating child constraints
2430 bool wxWindow::DoPhase(int phase
)
2432 int noIterations
= 0;
2433 int maxIterations
= 500;
2437 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2441 wxNode
*node
= GetChildren()->First();
2444 wxWindow
*child
= (wxWindow
*)node
->Data();
2445 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2447 wxLayoutConstraints
*constr
= child
->GetConstraints();
2450 if (succeeded
.Member(child
))
2455 int tempNoChanges
= 0;
2456 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2457 noChanges
+= tempNoChanges
;
2460 succeeded
.Append(child
);
2465 node
= node
->Next();
2472 void wxWindow::ResetConstraints(void)
2474 wxLayoutConstraints
*constr
= GetConstraints();
2477 constr
->left
.SetDone(FALSE
);
2478 constr
->top
.SetDone(FALSE
);
2479 constr
->right
.SetDone(FALSE
);
2480 constr
->bottom
.SetDone(FALSE
);
2481 constr
->width
.SetDone(FALSE
);
2482 constr
->height
.SetDone(FALSE
);
2483 constr
->centreX
.SetDone(FALSE
);
2484 constr
->centreY
.SetDone(FALSE
);
2486 wxNode
*node
= GetChildren()->First();
2489 wxWindow
*win
= (wxWindow
*)node
->Data();
2490 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2491 win
->ResetConstraints();
2492 node
= node
->Next();
2496 // Need to distinguish between setting the 'fake' size for
2497 // windows and sizers, and setting the real values.
2498 void wxWindow::SetConstraintSizes(bool recurse
)
2500 wxLayoutConstraints
*constr
= GetConstraints();
2501 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2502 constr
->width
.GetDone() && constr
->height
.GetDone())
2504 int x
= constr
->left
.GetValue();
2505 int y
= constr
->top
.GetValue();
2506 int w
= constr
->width
.GetValue();
2507 int h
= constr
->height
.GetValue();
2509 // If we don't want to resize this window, just move it...
2510 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2511 (constr
->height
.GetRelationship() != wxAsIs
))
2513 // Calls Layout() recursively. AAAGH. How can we stop that.
2514 // Simply take Layout() out of non-top level OnSizes.
2515 SizerSetSize(x
, y
, w
, h
);
2524 char *windowClass
= this->GetClassInfo()->GetClassName();
2527 if (GetName() == "")
2528 winName
= _("unnamed");
2530 winName
= GetName();
2531 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2532 if (!constr
->left
.GetDone())
2533 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2534 if (!constr
->right
.GetDone())
2535 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2536 if (!constr
->width
.GetDone())
2537 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2538 if (!constr
->height
.GetDone())
2539 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2540 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2545 wxNode
*node
= GetChildren()->First();
2548 wxWindow
*win
= (wxWindow
*)node
->Data();
2549 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2550 win
->SetConstraintSizes();
2551 node
= node
->Next();
2556 // This assumes that all sizers are 'on' the same
2557 // window, i.e. the parent of this window.
2558 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2560 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2561 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2565 m_sizerParent
->GetPosition(&xp
, &yp
);
2566 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2571 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2575 TransformSizerToActual(&xx
, &yy
);
2576 SetSize(xx
, yy
, w
, h
);
2579 void wxWindow::SizerMove(int x
, int y
)
2583 TransformSizerToActual(&xx
, &yy
);
2587 // Only set the size/position of the constraint (if any)
2588 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2590 wxLayoutConstraints
*constr
= GetConstraints();
2595 constr
->left
.SetValue(x
);
2596 constr
->left
.SetDone(TRUE
);
2600 constr
->top
.SetValue(y
);
2601 constr
->top
.SetDone(TRUE
);
2605 constr
->width
.SetValue(w
);
2606 constr
->width
.SetDone(TRUE
);
2610 constr
->height
.SetValue(h
);
2611 constr
->height
.SetDone(TRUE
);
2616 void wxWindow::MoveConstraint(int x
, int y
)
2618 wxLayoutConstraints
*constr
= GetConstraints();
2623 constr
->left
.SetValue(x
);
2624 constr
->left
.SetDone(TRUE
);
2628 constr
->top
.SetValue(y
);
2629 constr
->top
.SetDone(TRUE
);
2634 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2636 wxLayoutConstraints
*constr
= GetConstraints();
2639 *w
= constr
->width
.GetValue();
2640 *h
= constr
->height
.GetValue();
2646 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2648 wxLayoutConstraints
*constr
= GetConstraints();
2651 *w
= constr
->width
.GetValue();
2652 *h
= constr
->height
.GetValue();
2655 GetClientSize(w
, h
);
2658 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2660 wxLayoutConstraints
*constr
= GetConstraints();
2663 *x
= constr
->left
.GetValue();
2664 *y
= constr
->top
.GetValue();
2670 bool wxWindow::AcceptsFocus() const
2672 return IsEnabled() && IsShown();
2675 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )