1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
24 #include "wx/dcclient.h"
27 #include "wx/statusbr.h"
29 #include "wx/settings.h"
36 #include "gdk/gdkprivate.h"
37 #include "gdk/gdkkeysyms.h"
38 #include "wx/gtk/win_gtk.h"
40 //-----------------------------------------------------------------------------
41 // documentation on internals
42 //-----------------------------------------------------------------------------
45 I have been asked several times about writing some documentation about
46 the GTK port of wxWindows, especially its internal structures. Obviously,
47 you cannot understand wxGTK without knowing a little about the GTK, but
48 some more information about what the wxWindow, which is the base class
49 for all other window classes, does seems required as well.
51 What does wxWindow do? It contains the common interface for the following
52 jobs of its descendants:
54 1) Define the rudimentary behaviour common to all window classes, such as
55 resizing, intercepting user input (so as to make it possible to use these
56 events for special purposes in a derived class), window names etc.
58 2) Provide the possibility to contain and manage children, if the derived
59 class is allowed to contain children, which holds true for those window
60 classes which do not display a native GTK widget. To name them, these
61 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
62 work classes are a special case and are handled a bit differently from
63 the rest. The same holds true for the wxNotebook class.
65 3) Provide the possibility to draw into a client area of a window. This,
66 too, only holds true for classes that do not display a native GTK widget
69 4) Provide the entire mechanism for scrolling widgets. This actual inter-
70 face for this is usually in wxScrolledWindow, but the GTK implementation
73 5) A multitude of helper or extra methods for special purposes, such as
74 Drag'n'Drop, managing validators etc.
76 Normally one might expect, that one wxWindows window would always correspond
77 to one GTK widget. Under GTK, there is no such allround widget that has all
78 the functionality. Moreover, the GTK defines a client area as a different
79 widget from the actual widget you are handling. Last but not least some
80 special classes (e.g. wxFrame) handle different categories of widgets and
81 still have the possibility to draw something in the client area.
82 It was therefore required to write a special purpose GTK widget, that would
83 represent a client area in the sense of wxWindows capable to do the jobs
84 2), 3) and 4). I have written this class and it resides in win_gtk.c of
87 All windows must have a widget, with which they interact with other under-
88 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
89 thw wxWindow class has a member variable called m_widget which holds a
90 pointer to this widget. When the window class represents a GTK native widget,
91 this is (in most cases) the only GTK widget the class manages. E.g. the
92 wxStatitText class handles only a GtkLabel widget a pointer to which you
93 can find in m_widget (defined in wxWindow)
95 When the class has a client area for drawing into and for containing children
96 it has to handle the client area widget (of the type GtkMyFixed, defined in
97 win_gtk.c), but there could be any number of widgets, handled by a class
98 The common rule for all windows is only, that the widget that interacts with
99 the rest of GTK must be referenced in m_widget and all other widgets must be
100 children of this widget on the GTK level. The top-most widget, which also
101 represents the client area, must be in the m_wxwindow field and must be of
104 As I said, the window classes that display a GTK native widget only have
105 one widget, so in the case of e.g. the wxButton class m_widget holds a
106 pointer to a GtkButton widget. But windows with client areas (for drawing
107 and children) have a m_widget field that is a pointer to a GtkScrolled-
108 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
109 one is (in the GTK sense) a child of the GtkScrolledWindow.
111 If the m_wxwindow field is set, then all input to this widget is inter-
112 cepted and sent to the wxWindows class. If not, all input to the widget
113 that gets pointed to by m_widget gets intercepted and sent to the class.
117 //-------------------------------------------------------------------------
118 // conditional compilation
119 //-------------------------------------------------------------------------
121 #if (GTK_MINOR_VERSION == 1)
122 #if (GTK_MICRO_VERSION >= 5)
123 #define NEW_GTK_SCROLL_CODE
127 //-----------------------------------------------------------------------------
129 //-----------------------------------------------------------------------------
133 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
134 GdkEvent
*WXUNUSED(event
),
137 printf( "FOCUS NOW AT: " );
144 void debug_focus_in( GtkWidget
* widget
, const char* name
, const char *window
)
152 char *s
= new char[tmp
.Length()+1];
154 strcpy( s
, WXSTRINGCAST tmp
);
156 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
157 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
162 //-----------------------------------------------------------------------------
164 //-----------------------------------------------------------------------------
166 extern wxList wxPendingDelete
;
167 extern wxList wxTopLevelWindows
;
168 extern bool g_blockEventsOnDrag
;
169 extern bool g_blockEventsOnScroll
;
170 static bool g_capturing
= FALSE
;
171 static wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
173 // hack: we need something to pass to gtk_menu_popup, so we store the time of
174 // the last click here
175 static guint32 gs_timeLastClick
= 0;
177 //-----------------------------------------------------------------------------
178 // "expose_event" (of m_wxwindow, not of m_widget)
179 //-----------------------------------------------------------------------------
181 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
183 if (!win
->HasVMT()) return;
185 win
->m_updateRegion
.Union( gdk_event
->area
.x
,
187 gdk_event
->area
.width
,
188 gdk_event
->area
.height
);
190 if (gdk_event
->count
> 0) return;
193 printf( "OnExpose from " );
194 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
195 printf( win->GetClassInfo()->GetClassName() );
199 wxPaintEvent
event( win
->GetId() );
200 event
.SetEventObject( win
);
201 win
->GetEventHandler()->ProcessEvent( event
);
203 win
->m_updateRegion
.Clear();
206 //-----------------------------------------------------------------------------
207 // "draw" (of m_wxwindow, not of m_widget)
208 //-----------------------------------------------------------------------------
210 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
212 if (!win
->HasVMT()) return;
214 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
216 wxPaintEvent
event( win
->GetId() );
217 event
.SetEventObject( win
);
218 win
->GetEventHandler()->ProcessEvent( event
);
220 win
->m_updateRegion
.Clear();
223 //-----------------------------------------------------------------------------
224 // "key_press_event" from any window
225 //-----------------------------------------------------------------------------
227 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
229 if (!win
->HasVMT()) return FALSE
;
230 if (g_blockEventsOnDrag
) return FALSE
;
233 printf( "OnKeyPress from " );
234 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
235 printf( win->GetClassInfo()->GetClassName() );
240 switch (gdk_event
->keyval
)
242 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
243 case GDK_Tab
: key_code
= WXK_TAB
; break;
244 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
245 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
246 case GDK_Return
: key_code
= WXK_RETURN
; break;
247 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
248 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
249 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
250 case GDK_Delete
: key_code
= WXK_DELETE
; break;
251 case GDK_Home
: key_code
= WXK_HOME
; break;
252 case GDK_Left
: key_code
= WXK_LEFT
; break;
253 case GDK_Up
: key_code
= WXK_UP
; break;
254 case GDK_Right
: key_code
= WXK_RIGHT
; break;
255 case GDK_Down
: key_code
= WXK_DOWN
; break;
256 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
257 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
258 case GDK_Next
: key_code
= WXK_NEXT
; break;
259 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
260 case GDK_End
: key_code
= WXK_END
; break;
261 case GDK_Begin
: key_code
= WXK_HOME
; break;
262 case GDK_Select
: key_code
= WXK_SELECT
; break;
263 case GDK_Print
: key_code
= WXK_PRINT
; break;
264 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
265 case GDK_Insert
: key_code
= WXK_INSERT
; break;
266 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
267 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
268 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
269 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
270 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
271 case GDK_KP_Up
: key_code
= WXK_UP
; break;
272 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
273 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
274 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
275 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
276 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
277 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
278 case GDK_KP_End
: key_code
= WXK_END
; break;
279 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
280 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
281 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
282 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
283 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
284 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
285 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
286 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
287 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
288 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
289 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
290 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
291 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
292 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
293 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
294 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
295 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
296 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
297 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
298 case GDK_F1
: key_code
= WXK_F1
; break;
299 case GDK_F2
: key_code
= WXK_F2
; break;
300 case GDK_F3
: key_code
= WXK_F3
; break;
301 case GDK_F4
: key_code
= WXK_F4
; break;
302 case GDK_F5
: key_code
= WXK_F5
; break;
303 case GDK_F6
: key_code
= WXK_F6
; break;
304 case GDK_F7
: key_code
= WXK_F7
; break;
305 case GDK_F8
: key_code
= WXK_F8
; break;
306 case GDK_F9
: key_code
= WXK_F9
; break;
307 case GDK_F10
: key_code
= WXK_F10
; break;
308 case GDK_F11
: key_code
= WXK_F11
; break;
309 case GDK_F12
: key_code
= WXK_F12
; break;
312 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
313 key_code
= gdk_event
->keyval
;
317 if (!key_code
) return FALSE
;
319 wxKeyEvent
event( wxEVT_CHAR
);
320 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
321 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
322 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
323 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
324 event
.m_keyCode
= key_code
;
327 event
.SetEventObject( win
);
329 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
333 wxWindow
*ancestor
= win
;
336 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
339 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
340 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
343 ancestor
= ancestor
->GetParent();
347 // win is a control: tab can be propagated up
348 if ((!ret
) && (gdk_event
->keyval
== GDK_Tab
))
350 wxNavigationKeyEvent new_event
;
351 new_event
.SetDirection( !(gdk_event
->state
& GDK_SHIFT_MASK
) );
352 new_event
.SetWindowChange( FALSE
);
353 new_event
.SetCurrentFocus( win
);
354 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
358 // win is a panel: up can be propagated to the panel
359 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
360 (gdk_event->keyval == GDK_Up))
362 win->m_parent->SetFocus();
366 // win is a panel: left/right can be propagated to the panel
367 if ((!ret) && (win->m_wxwindow) &&
368 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
369 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
371 wxNavigationKeyEvent new_event;
372 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
373 new_event.SetCurrentFocus( win );
374 ret = win->GetEventHandler()->ProcessEvent( new_event );
380 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
386 //-----------------------------------------------------------------------------
387 // "button_press_event"
388 //-----------------------------------------------------------------------------
390 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
392 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
394 if (g_blockEventsOnDrag
) return TRUE
;
395 if (g_blockEventsOnScroll
) return TRUE
;
399 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
401 gtk_widget_grab_focus (win
->m_wxwindow
);
404 printf( "GrabFocus from " );
405 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
406 printf( win->GetClassInfo()->GetClassName() );
413 if (!win
->HasVMT()) return TRUE
;
416 printf( "OnButtonPress from " );
417 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
418 printf( win->GetClassInfo()->GetClassName() );
422 wxEventType event_type
= wxEVT_LEFT_DOWN
;
424 if (gdk_event
->button
== 1)
426 switch (gdk_event
->type
)
428 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
429 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
433 else if (gdk_event
->button
== 2)
435 switch (gdk_event
->type
)
437 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
438 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
442 else if (gdk_event
->button
== 3)
444 switch (gdk_event
->type
)
446 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
447 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
452 wxMouseEvent
event( event_type
);
453 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
454 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
455 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
456 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
457 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
458 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
459 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
461 event
.m_x
= (long)gdk_event
->x
;
462 event
.m_y
= (long)gdk_event
->y
;
464 // Some control don't have their own X window and thus cannot get
469 wxNode
*node
= win
->GetChildren().First();
472 wxWindow
*child
= (wxWindow
*)node
->Data();
474 if (child
->m_isStaticBox
)
476 // wxStaticBox is transparent in the box itself
479 int xx1
= child
->m_x
;
480 int yy1
= child
->m_y
;
481 int xx2
= child
->m_x
+ child
->m_width
;
482 int yy2
= child
->m_x
+ child
->m_height
;
485 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
487 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
489 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
491 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
494 event
.m_x
-= child
->m_x
;
495 event
.m_y
-= child
->m_y
;
502 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
503 (child
->m_x
<= event
.m_x
) &&
504 (child
->m_y
<= event
.m_y
) &&
505 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
506 (child
->m_y
+child
->m_height
>= event
.m_y
))
509 event
.m_x
-= child
->m_x
;
510 event
.m_y
-= child
->m_y
;
518 event
.SetEventObject( win
);
520 gs_timeLastClick
= gdk_event
->time
;
522 if (win
->GetEventHandler()->ProcessEvent( event
))
523 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
528 //-----------------------------------------------------------------------------
529 // "button_release_event"
530 //-----------------------------------------------------------------------------
532 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
534 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
536 if (g_blockEventsOnDrag
) return TRUE
;
537 if (g_blockEventsOnScroll
) return TRUE
;
539 if (!win
->HasVMT()) return TRUE
;
542 printf( "OnButtonRelease from " );
543 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
544 printf( win->GetClassInfo()->GetClassName() );
548 wxEventType event_type
= wxEVT_NULL
;
550 switch (gdk_event
->button
)
552 case 1: event_type
= wxEVT_LEFT_UP
; break;
553 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
554 case 3: event_type
= wxEVT_RIGHT_UP
; break;
557 wxMouseEvent
event( event_type
);
558 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
559 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
560 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
561 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
562 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
563 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
564 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
565 event
.m_x
= (long)gdk_event
->x
;
566 event
.m_y
= (long)gdk_event
->y
;
568 // Some control don't have their own X window and thus cannot get
573 wxNode
*node
= win
->GetChildren().First();
576 wxWindow
*child
= (wxWindow
*)node
->Data();
578 if (child
->m_isStaticBox
)
580 // wxStaticBox is transparent in the box itself
583 int xx1
= child
->m_x
;
584 int yy1
= child
->m_y
;
585 int xx2
= child
->m_x
+ child
->m_width
;
586 int yy2
= child
->m_x
+ child
->m_height
;
589 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
591 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
593 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
595 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
598 event
.m_x
-= child
->m_x
;
599 event
.m_y
-= child
->m_y
;
606 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
607 (child
->m_x
<= event
.m_x
) &&
608 (child
->m_y
<= event
.m_y
) &&
609 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
610 (child
->m_y
+child
->m_height
>= event
.m_y
))
613 event
.m_x
-= child
->m_x
;
614 event
.m_y
-= child
->m_y
;
622 event
.SetEventObject( win
);
624 if (win
->GetEventHandler()->ProcessEvent( event
))
625 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
630 //-----------------------------------------------------------------------------
631 // "motion_notify_event"
632 //-----------------------------------------------------------------------------
634 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
636 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
638 if (g_blockEventsOnDrag
) return TRUE
;
639 if (g_blockEventsOnScroll
) return TRUE
;
641 if (!win
->HasVMT()) return TRUE
;
644 printf( "OnMotion from " );
645 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
646 printf( win->GetClassInfo()->GetClassName() );
650 wxMouseEvent
event( wxEVT_MOTION
);
651 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
652 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
653 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
654 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
655 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
656 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
657 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
659 event
.m_x
= (long)gdk_event
->x
;
660 event
.m_y
= (long)gdk_event
->y
;
662 // Some control don't have their own X window and thus cannot get
667 wxNode
*node
= win
->GetChildren().First();
670 wxWindow
*child
= (wxWindow
*)node
->Data();
672 if (child
->m_isStaticBox
)
674 // wxStaticBox is transparent in the box itself
677 int xx1
= child
->m_x
;
678 int yy1
= child
->m_y
;
679 int xx2
= child
->m_x
+ child
->m_width
;
680 int yy2
= child
->m_x
+ child
->m_height
;
683 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
685 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
687 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
689 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
692 event
.m_x
-= child
->m_x
;
693 event
.m_y
-= child
->m_y
;
700 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
701 (child
->m_x
<= event
.m_x
) &&
702 (child
->m_y
<= event
.m_y
) &&
703 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
704 (child
->m_y
+child
->m_height
>= event
.m_y
))
707 event
.m_x
-= child
->m_x
;
708 event
.m_y
-= child
->m_y
;
716 event
.SetEventObject( win
);
718 if (win
->GetEventHandler()->ProcessEvent( event
))
719 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
724 //-----------------------------------------------------------------------------
726 //-----------------------------------------------------------------------------
728 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
730 if (g_blockEventsOnDrag
) return TRUE
;
736 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
738 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
740 printf( "SetFocus flag from " );
741 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
742 printf( win->GetClassInfo()->GetClassName() );
748 if (!win
->HasVMT()) return TRUE
;
751 printf( "OnSetFocus from " );
752 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
753 printf( win->GetClassInfo()->GetClassName() );
755 printf( WXSTRINGCAST win->GetLabel() );
759 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
760 event
.SetEventObject( win
);
762 if (win
->GetEventHandler()->ProcessEvent( event
))
763 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
768 //-----------------------------------------------------------------------------
770 //-----------------------------------------------------------------------------
772 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
774 if (g_blockEventsOnDrag
) return TRUE
;
777 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
778 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
781 if (!win
->HasVMT()) return TRUE
;
784 printf( "OnKillFocus from " );
785 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
786 printf( win->GetClassInfo()->GetClassName() );
790 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
791 event
.SetEventObject( win
);
793 if (win
->GetEventHandler()->ProcessEvent( event
))
794 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
799 //-----------------------------------------------------------------------------
800 // "enter_notify_event"
801 //-----------------------------------------------------------------------------
803 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
805 if (g_blockEventsOnDrag
) return TRUE
;
807 if ((widget
->window
) && (win
->m_cursor
))
808 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
810 if (widget
->window
!= gdk_event
->window
) return TRUE
;
812 if (!win
->HasVMT()) return TRUE
;
815 printf( "OnEnter from " );
816 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
817 printf( win->GetClassInfo()->GetClassName() );
821 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
822 event
.SetEventObject( win
);
826 GdkModifierType state
= (GdkModifierType
)0;
828 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
830 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
831 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
832 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
833 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
834 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
835 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
836 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
841 if (win
->GetEventHandler()->ProcessEvent( event
))
842 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
847 //-----------------------------------------------------------------------------
848 // "leave_notify_event"
849 //-----------------------------------------------------------------------------
851 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
853 if (g_blockEventsOnDrag
) return TRUE
;
855 if ((widget
->window
) && (win
->m_cursor
))
856 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
858 if (widget
->window
!= gdk_event
->window
) return TRUE
;
860 if (!win
->HasVMT()) return TRUE
;
863 printf( "OnLeave from " );
864 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
865 printf( win->GetClassInfo()->GetClassName() );
869 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
870 event
.SetEventObject( win
);
874 GdkModifierType state
= (GdkModifierType
)0;
876 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
878 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
879 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
880 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
881 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
882 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
883 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
884 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
889 if (win
->GetEventHandler()->ProcessEvent( event
))
890 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
895 //-----------------------------------------------------------------------------
896 // "value_changed" from m_vAdjust
897 //-----------------------------------------------------------------------------
899 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
901 if (g_blockEventsOnDrag
) return;
904 printf( "OnVScroll from " );
905 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
906 printf( win->GetClassInfo()->GetClassName() );
910 if (!win
->HasVMT()) return;
912 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
913 if (fabs(diff
) < 0.2) return;
915 wxEventType command
= wxEVT_NULL
;
917 float line_step
= win
->m_vAdjust
->step_increment
;
918 float page_step
= win
->m_vAdjust
->page_increment
;
920 if (win
->m_isScrolling
)
922 command
= wxEVT_SCROLL_THUMBTRACK
;
926 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLL_BOTTOM
;
927 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLL_TOP
;
928 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
929 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
930 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
931 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
932 else command
= wxEVT_SCROLL_THUMBTRACK
;
935 int value
= (int)(win
->m_vAdjust
->value
+0.5);
937 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
938 event
.SetEventObject( win
);
939 win
->GetEventHandler()->ProcessEvent( event
);
942 //-----------------------------------------------------------------------------
943 // "value_changed" from m_hAdjust
944 //-----------------------------------------------------------------------------
946 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
948 if (g_blockEventsOnDrag
) return;
951 printf( "OnHScroll from " );
952 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
953 printf( win->GetClassInfo()->GetClassName() );
957 if (!win
->HasVMT()) return;
959 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
960 if (fabs(diff
) < 0.2) return;
962 wxEventType command
= wxEVT_NULL
;
964 float line_step
= win
->m_hAdjust
->step_increment
;
965 float page_step
= win
->m_hAdjust
->page_increment
;
967 if (win
->m_isScrolling
)
969 command
= wxEVT_SCROLL_THUMBTRACK
;
973 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLL_BOTTOM
;
974 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLL_TOP
;
975 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
976 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
977 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
978 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
979 else command
= wxEVT_SCROLL_THUMBTRACK
;
982 int value
= (int)(win
->m_hAdjust
->value
+0.5);
984 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
985 event
.SetEventObject( win
);
986 win
->GetEventHandler()->ProcessEvent( event
);
989 //-----------------------------------------------------------------------------
990 // "changed" from m_vAdjust
991 //-----------------------------------------------------------------------------
993 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
995 if (g_blockEventsOnDrag
) return;
998 printf( "OnVScroll change from " );
999 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1000 printf( win->GetClassInfo()->GetClassName() );
1004 if (!win
->HasVMT()) return;
1006 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
1007 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1009 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
1010 event
.SetEventObject( win
);
1011 win
->GetEventHandler()->ProcessEvent( event
);
1014 //-----------------------------------------------------------------------------
1015 // "changed" from m_hAdjust
1016 //-----------------------------------------------------------------------------
1018 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1020 if (g_blockEventsOnDrag
) return;
1023 printf( "OnHScroll change from " );
1024 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1025 printf( win->GetClassInfo()->GetClassName() );
1029 if (!win
->HasVMT()) return;
1031 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
1032 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1034 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
1035 event
.SetEventObject( win
);
1036 win
->GetEventHandler()->ProcessEvent( event
);
1039 //-----------------------------------------------------------------------------
1040 // "button_press_event" from scrollbar
1041 //-----------------------------------------------------------------------------
1043 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1044 GdkEventButton
*WXUNUSED(gdk_event
),
1047 // don't test here as we can release the mouse while being over
1048 // a different window then the slider
1050 // if (gdk_event->window != widget->slider) return FALSE;
1052 win
->m_isScrolling
= TRUE
;
1053 g_blockEventsOnScroll
= TRUE
;
1058 //-----------------------------------------------------------------------------
1059 // "button_release_event" from scrollbar
1060 //-----------------------------------------------------------------------------
1062 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1063 GdkEventButton
*WXUNUSED(gdk_event
),
1067 // don't test here as we can release the mouse while being over
1068 // a different window then the slider
1070 // if (gdk_event->window != widget->slider) return FALSE;
1072 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1074 if (widget
== GTK_RANGE(s_window
->vscrollbar
))
1075 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1077 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1079 win
->m_isScrolling
= FALSE
;
1080 g_blockEventsOnScroll
= FALSE
;
1085 //-----------------------------------------------------------------------------
1086 // InsertChild for wxWindow.
1087 //-----------------------------------------------------------------------------
1089 // Callback for wxWindow. This very strange beast has to be used because
1090 // C++ has no virtual methods in a constructor. We have to emulate a
1091 // virtual function here as wxNotebook requires a different way to insert
1092 // a child in it. I had opted for creating a wxNotebookPage window class
1093 // which would have made this superfluous (such in the MDI window system),
1094 // but no-one was listening to me...
1096 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1098 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1099 GTK_WIDGET(child
->m_widget
),
1103 gtk_widget_set_usize( GTK_WIDGET(child
->m_widget
),
1108 //-----------------------------------------------------------------------------
1110 //-----------------------------------------------------------------------------
1112 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
1114 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
1115 EVT_SIZE(wxWindow::OnSize
)
1116 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
1117 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
1118 EVT_IDLE(wxWindow::OnIdle
)
1121 wxWindow::wxWindow()
1123 m_widget
= (GtkWidget
*) NULL
;
1124 m_wxwindow
= (GtkWidget
*) NULL
;
1125 m_parent
= (wxWindow
*) NULL
;
1126 m_children
.DeleteContents( FALSE
);
1139 m_eventHandler
= this;
1140 m_windowValidator
= (wxValidator
*) NULL
;
1144 m_cursor
= (wxCursor
*) NULL
;
1145 m_font
= *wxSWISS_FONT
;
1147 m_windowName
= "noname";
1149 m_constraints
= (wxLayoutConstraints
*) NULL
;
1150 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1151 m_windowSizer
= (wxSizer
*) NULL
;
1152 m_sizerParent
= (wxWindow
*) NULL
;
1153 m_autoLayout
= FALSE
;
1157 m_needParent
= TRUE
;
1159 m_hasScrolling
= FALSE
;
1160 m_isScrolling
= FALSE
;
1161 m_hAdjust
= (GtkAdjustment
*) NULL
;
1162 m_vAdjust
= (GtkAdjustment
*) NULL
;
1163 m_oldHorizontalPos
= 0.0;
1164 m_oldVerticalPos
= 0.0;
1169 m_dropTarget
= (wxDropTarget
*) NULL
;
1171 m_scrollGC
= (GdkGC
*) NULL
;
1172 m_widgetStyle
= (GtkStyle
*) NULL
;
1174 m_insertCallback
= wxInsertChildInWindow
;
1176 m_clientObject
= (wxClientData
*) NULL
;
1177 m_clientData
= NULL
;
1179 m_isStaticBox
= FALSE
;
1180 m_acceptsFocus
= FALSE
;
1183 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1184 const wxPoint
&pos
, const wxSize
&size
,
1185 long style
, const wxString
&name
)
1187 m_insertCallback
= wxInsertChildInWindow
;
1188 Create( parent
, id
, pos
, size
, style
, name
);
1191 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1192 const wxPoint
&pos
, const wxSize
&size
,
1193 long style
, const wxString
&name
)
1197 m_needParent
= TRUE
;
1199 PreCreation( parent
, id
, pos
, size
, style
, name
);
1201 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1202 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1205 debug_focus_in( m_widget
, "wxWindow::m_widget", name
);
1208 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(m_widget
);
1211 debug_focus_in( s_window
->hscrollbar
, "wxWindow::hsrcollbar", name
);
1212 debug_focus_in( s_window
->vscrollbar
, "wxWindow::vsrcollbar", name
);
1215 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1216 scroll_class
->scrollbar_spacing
= 0;
1218 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1220 m_oldHorizontalPos
= 0.0;
1221 m_oldVerticalPos
= 0.0;
1223 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
1224 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
1226 m_wxwindow
= gtk_myfixed_new();
1229 debug_focus_in( m_wxwindow
, "wxWindow::m_wxwindow", name
);
1232 #ifdef NEW_GTK_SCROLL_CODE
1233 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget
), m_wxwindow
);
1234 GtkViewport
*viewport
= GTK_VIEWPORT(s_window
->child
);
1236 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1237 GtkViewport
*viewport
= GTK_VIEWPORT(s_window
->viewport
);
1241 debug_focus_in( GTK_WIDGET(viewport
), "wxWindow::viewport", name
);
1244 if (m_windowStyle
& wxRAISED_BORDER
)
1246 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1248 else if (m_windowStyle
& wxSUNKEN_BORDER
)
1250 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1254 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1257 if ((m_windowStyle
& wxTAB_TRAVERSAL
) != 0)
1259 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1260 m_acceptsFocus
= FALSE
;
1264 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1265 m_acceptsFocus
= TRUE
;
1268 // shut the viewport up
1269 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1270 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1272 // I _really_ don't want scrollbars in the beginning
1273 m_vAdjust
->lower
= 0.0;
1274 m_vAdjust
->upper
= 1.0;
1275 m_vAdjust
->value
= 0.0;
1276 m_vAdjust
->step_increment
= 1.0;
1277 m_vAdjust
->page_increment
= 1.0;
1278 m_vAdjust
->page_size
= 5.0;
1279 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1280 m_hAdjust
->lower
= 0.0;
1281 m_hAdjust
->upper
= 1.0;
1282 m_hAdjust
->value
= 0.0;
1283 m_hAdjust
->step_increment
= 1.0;
1284 m_hAdjust
->page_increment
= 1.0;
1285 m_hAdjust
->page_size
= 5.0;
1286 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1288 // these handlers block mouse events to any window during scrolling
1289 // such as motion events and prevent GTK and wxWindows from fighting
1290 // over where the slider should be
1292 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_press_event",
1293 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1295 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_press_event",
1296 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1298 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_release_event",
1299 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1301 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_release_event",
1302 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1304 // these handers het notified when screen updates are required either when
1305 // scrolling or when the window size (and therefore scrollbar configuration)
1308 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1309 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1310 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1311 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1313 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1314 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1315 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1316 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1318 gtk_widget_show( m_wxwindow
);
1320 if (m_parent
) m_parent
->AddChild( this );
1322 (m_parent
->m_insertCallback
)( m_parent
, this );
1331 wxWindow::~wxWindow()
1335 if (m_dropTarget
) delete m_dropTarget
;
1337 if (m_parent
) m_parent
->RemoveChild( this );
1338 if (m_widget
) Show( FALSE
);
1342 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
1344 if (m_scrollGC
) gdk_gc_unref( m_scrollGC
);
1346 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
1348 if (m_widget
) gtk_widget_destroy( m_widget
);
1350 if (m_cursor
) delete m_cursor
;
1352 DeleteRelatedConstraints();
1355 // This removes any dangling pointers to this window
1356 // in other windows' constraintsInvolvedIn lists.
1357 UnsetConstraints(m_constraints
);
1358 delete m_constraints
;
1359 m_constraints
= (wxLayoutConstraints
*) NULL
;
1363 delete m_windowSizer
;
1364 m_windowSizer
= (wxSizer
*) NULL
;
1366 // If this is a child of a sizer, remove self from parent
1367 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
1369 // Just in case the window has been Closed, but
1370 // we're then deleting immediately: don't leave
1371 // dangling pointers.
1372 wxPendingDelete
.DeleteObject(this);
1374 // Just in case we've loaded a top-level window via
1375 // wxWindow::LoadNativeDialog but we weren't a dialog
1377 wxTopLevelWindows
.DeleteObject(this);
1379 if (m_windowValidator
) delete m_windowValidator
;
1381 if (m_clientObject
) delete m_clientObject
;
1384 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1385 const wxPoint
&pos
, const wxSize
&size
,
1386 long style
, const wxString
&name
)
1388 wxASSERT_MSG( (!m_needParent
) || (parent
), "Need complete parent." );
1390 m_widget
= (GtkWidget
*) NULL
;
1391 m_wxwindow
= (GtkWidget
*) NULL
;
1394 m_children
.DeleteContents( FALSE
);
1397 if (m_width
== -1) m_width
= 20;
1399 if (m_height
== -1) m_height
= 20;
1404 if (!m_needParent
) // some reasonable defaults
1408 m_x
= (gdk_screen_width () - m_width
) / 2;
1409 if (m_x
< 10) m_x
= 10;
1413 m_y
= (gdk_screen_height () - m_height
) / 2;
1414 if (m_y
< 10) m_y
= 10;
1425 m_eventHandler
= this;
1427 m_windowId
= id
== -1 ? wxNewId() : id
;
1431 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1432 m_font
= *wxSWISS_FONT
;
1433 m_backgroundColour
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
1434 m_foregroundColour
= *wxBLACK
;
1435 m_windowStyle
= style
;
1436 m_windowName
= name
;
1438 m_constraints
= (wxLayoutConstraints
*) NULL
;
1439 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1440 m_windowSizer
= (wxSizer
*) NULL
;
1441 m_sizerParent
= (wxWindow
*) NULL
;
1442 m_autoLayout
= FALSE
;
1444 m_hasScrolling
= FALSE
;
1445 m_isScrolling
= FALSE
;
1446 m_hAdjust
= (GtkAdjustment
*) NULL
;
1447 m_vAdjust
= (GtkAdjustment
*) NULL
;
1448 m_oldHorizontalPos
= 0.0;
1449 m_oldVerticalPos
= 0.0;
1454 m_dropTarget
= (wxDropTarget
*) NULL
;
1456 m_windowValidator
= (wxValidator
*) NULL
;
1457 m_scrollGC
= (GdkGC
*) NULL
;
1458 m_widgetStyle
= (GtkStyle
*) NULL
;
1460 m_clientObject
= (wxClientData
*)NULL
;
1461 m_clientData
= NULL
;
1463 m_isStaticBox
= FALSE
;
1466 void wxWindow::PostCreation()
1470 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1471 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1473 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1474 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1477 ConnectWidget( GetConnectWidget() );
1479 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1481 if (m_wxwindow
) gtk_widget_realize( m_wxwindow
);
1483 SetCursor( *wxSTANDARD_CURSOR
);
1488 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1490 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1491 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1493 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1494 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1496 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1497 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1499 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1500 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1502 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1503 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1505 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1506 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1508 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1509 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1511 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1512 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1515 bool wxWindow::HasVMT()
1520 bool wxWindow::Close( bool force
)
1522 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1524 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1525 event
.SetEventObject(this);
1526 event
.SetForce(force
);
1528 return GetEventHandler()->ProcessEvent(event
);
1531 bool wxWindow::Destroy()
1533 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1540 bool wxWindow::DestroyChildren()
1543 while ((node
= m_children
.First()) != (wxNode
*)NULL
)
1546 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1549 if (m_children
.Member(child
)) delete node
;
1555 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1557 // are we to set fonts here ?
1560 wxPoint
wxWindow::GetClientAreaOrigin() const
1562 return wxPoint(0,0);
1565 void wxWindow::AdjustForParentClientOrigin( int& x
, int& y
, int sizeFlags
)
1567 if (((sizeFlags
& wxSIZE_NO_ADJUSTMENTS
) == 0) && GetParent())
1569 wxPoint
pt(GetParent()->GetClientAreaOrigin());
1575 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1577 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1578 wxASSERT_MSG( (m_parent
!= NULL
), "wxWindow::SetSize requires parent.\n" );
1580 if (m_resizing
) return; // I don't like recursions
1583 if (m_parent
->m_wxwindow
== NULL
) // i.e. wxNotebook
1585 // don't set the size for children of wxNotebook, just take the values.
1593 int old_width
= m_width
;
1594 int old_height
= m_height
;
1596 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1598 if (x
!= -1) m_x
= x
;
1599 if (y
!= -1) m_y
= y
;
1600 if (width
!= -1) m_width
= width
;
1601 if (height
!= -1) m_height
= height
;
1611 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1613 if (width
== -1) m_width
= 80;
1616 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1618 if (height
== -1) m_height
= 26;
1621 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1622 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1623 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
1624 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
1626 wxPoint
pt( m_parent
->GetClientAreaOrigin() );
1627 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
+pt
.x
, m_y
+pt
.y
);
1629 if ((old_width
!= m_width
) || (old_height
!= m_height
))
1630 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1635 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1636 event
.SetEventObject( this );
1637 GetEventHandler()->ProcessEvent( event
);
1642 void wxWindow::SetSize( int width
, int height
)
1644 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1647 void wxWindow::Move( int x
, int y
)
1649 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1652 void wxWindow::GetSize( int *width
, int *height
) const
1654 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1656 if (width
) (*width
) = m_width
;
1657 if (height
) (*height
) = m_height
;
1660 void wxWindow::SetClientSize( int width
, int height
)
1662 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1666 SetSize( width
, height
);
1673 if (!m_hasScrolling
)
1675 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
1677 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1678 (m_windowStyle
& wxSUNKEN_BORDER
))
1680 dw
+= 2 * window_class
->xthickness
;
1681 dh
+= 2 * window_class
->ythickness
;
1686 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1687 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1689 #ifdef NEW_GTK_SCROLL_CODE
1690 GtkWidget
*viewport
= scroll_window
->child
;
1692 GtkWidget
*viewport
= scroll_window
->viewport
;
1695 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1697 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1698 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1700 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1701 (m_windowStyle
& wxSUNKEN_BORDER
))
1703 dw
+= 2 * viewport_class
->xthickness
;
1704 dh
+= 2 * viewport_class
->ythickness
;
1707 if (scroll_window
->vscrollbar_visible
)
1709 dw
+= vscrollbar
->allocation
.width
;
1710 dw
+= scroll_class
->scrollbar_spacing
;
1713 if (scroll_window
->hscrollbar_visible
)
1715 dh
+= hscrollbar
->allocation
.height
;
1716 dw
+= scroll_class
->scrollbar_spacing
;
1720 SetSize( width
+dw
, height
+dh
);
1724 void wxWindow::GetClientSize( int *width
, int *height
) const
1726 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1730 if (width
) (*width
) = m_width
;
1731 if (height
) (*height
) = m_height
;
1738 if (!m_hasScrolling
)
1740 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
1742 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1743 (m_windowStyle
& wxSUNKEN_BORDER
))
1745 dw
+= 2 * window_class
->xthickness
;
1746 dh
+= 2 * window_class
->ythickness
;
1751 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1752 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1754 #ifdef NEW_GTK_SCROLL_CODE
1755 GtkWidget
*viewport
= scroll_window
->child
;
1757 GtkWidget
*viewport
= scroll_window
->viewport
;
1760 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1762 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1763 (m_windowStyle
& wxSUNKEN_BORDER
))
1765 dw
+= 2 * viewport_class
->xthickness
;
1766 dh
+= 2 * viewport_class
->ythickness
;
1769 if (scroll_window
->vscrollbar_visible
)
1771 // dw += vscrollbar->allocation.width;
1772 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1773 dw
+= scroll_class
->scrollbar_spacing
;
1776 if (scroll_window
->hscrollbar_visible
)
1778 // dh += hscrollbar->allocation.height;
1780 dh
+= scroll_class
->scrollbar_spacing
;
1784 if (width
) (*width
) = m_width
- dw
;
1785 if (height
) (*height
) = m_height
- dh
;
1789 void wxWindow::GetPosition( int *x
, int *y
) const
1791 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1797 void wxWindow::ClientToScreen( int *x
, int *y
)
1799 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1801 GdkWindow
*source
= (GdkWindow
*) NULL
;
1803 source
= m_wxwindow
->window
;
1805 source
= m_widget
->window
;
1809 gdk_window_get_origin( source
, &org_x
, &org_y
);
1813 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1815 org_x
+= m_widget
->allocation
.x
;
1816 org_y
+= m_widget
->allocation
.y
;
1820 wxPoint
pt(GetClientAreaOrigin());
1828 void wxWindow::ScreenToClient( int *x
, int *y
)
1830 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1832 GdkWindow
*source
= (GdkWindow
*) NULL
;
1834 source
= m_wxwindow
->window
;
1836 source
= m_widget
->window
;
1840 gdk_window_get_origin( source
, &org_x
, &org_y
);
1844 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1846 org_x
+= m_widget
->allocation
.x
;
1847 org_y
+= m_widget
->allocation
.y
;
1851 wxPoint
pt(GetClientAreaOrigin());
1859 void wxWindow::Centre( int direction
)
1861 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1870 m_parent
->GetSize( &p_w
, &p_h
);
1871 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) x
= (p_w
- m_width
) / 2;
1872 if (direction
& wxVERTICAL
== wxVERTICAL
) y
= (p_h
- m_height
) / 2;
1876 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) x
= (gdk_screen_width () - m_width
) / 2;
1877 if (direction
& wxVERTICAL
== wxVERTICAL
) y
= (gdk_screen_height () - m_height
) / 2;
1883 void wxWindow::Fit()
1885 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1889 wxNode
*node
= m_children
.First();
1892 wxWindow
*win
= (wxWindow
*)node
->Data();
1894 win
->GetPosition(&wx
, &wy
);
1895 win
->GetSize(&ww
, &wh
);
1896 if (wx
+ ww
> maxX
) maxX
= wx
+ ww
;
1897 if (wy
+ wh
> maxY
) maxY
= wy
+ wh
;
1899 node
= node
->Next();
1902 SetClientSize(maxX
+ 7, maxY
+ 14);
1905 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1907 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1915 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1917 // if (GetAutoLayout()) Layout();
1920 bool wxWindow::Show( bool show
)
1922 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, "invalid window" );
1925 gtk_widget_show( m_widget
);
1927 gtk_widget_hide( m_widget
);
1934 void wxWindow::Enable( bool enable
)
1936 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1938 m_isEnabled
= enable
;
1940 gtk_widget_set_sensitive( m_widget
, enable
);
1941 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1944 int wxWindow::GetCharHeight() const
1946 wxCHECK_MSG( (m_widget
!= NULL
), 12, "invalid window" );
1948 wxCHECK_MSG( m_font
.Ok(), 12, "invalid font" );
1950 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1952 return font
->ascent
+ font
->descent
;
1955 int wxWindow::GetCharWidth() const
1957 wxCHECK_MSG( (m_widget
!= NULL
), 8, "invalid window" );
1959 wxCHECK_MSG( m_font
.Ok(), 8, "invalid font" );
1961 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1963 return gdk_string_width( font
, "H" );
1966 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1967 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1969 wxFont fontToUse
= m_font
;
1970 if (theFont
) fontToUse
= *theFont
;
1972 wxCHECK_RET( fontToUse
.Ok(), "invalid font" );
1974 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1975 if (x
) (*x
) = gdk_string_width( font
, string
);
1976 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1977 if (descent
) (*descent
) = font
->descent
;
1978 if (externalLeading
) (*externalLeading
) = 0; // ??
1981 void wxWindow::MakeModal( bool modal
)
1985 // Disable all other windows
1986 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1988 wxNode
*node
= wxTopLevelWindows
.First();
1991 wxWindow
*win
= (wxWindow
*)node
->Data();
1992 if (win
!= this) win
->Enable(!modal
);
1994 node
= node
->Next();
1999 void wxWindow::SetFocus()
2001 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2003 GtkWidget
*connect_widget
= GetConnectWidget();
2006 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2008 gtk_widget_grab_focus (connect_widget
);
2010 else if (GTK_IS_CONTAINER(connect_widget
))
2012 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2020 wxWindow
*wxWindow::FindFocus()
2022 return g_focusWindow
;
2025 bool wxWindow::AcceptsFocus() const
2027 return IsEnabled() && IsShown() && m_acceptsFocus
;
2030 bool wxWindow::OnClose()
2035 void wxWindow::AddChild( wxWindow
*child
)
2037 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2038 wxCHECK_RET( (child
!= NULL
), "invalid child" );
2040 m_children
.Append( child
);
2043 wxWindow
*wxWindow::ReParent( wxWindow
*newParent
)
2045 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, "invalid window" );
2047 wxWindow
*oldParent
= GetParent();
2049 if (oldParent
) oldParent
->RemoveChild( this );
2051 gtk_widget_unparent( m_widget
);
2055 newParent
->AddChild( this );
2056 (newParent
->m_insertCallback
)( newParent
, this );
2062 void wxWindow::RemoveChild( wxWindow
*child
)
2064 m_children
.DeleteObject( child
);
2065 child
->m_parent
= (wxWindow
*) NULL
;
2068 void wxWindow::SetReturnCode( int retCode
)
2070 m_retCode
= retCode
;
2073 int wxWindow::GetReturnCode()
2078 void wxWindow::Raise()
2080 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2082 if (m_widget
) gdk_window_raise( m_widget
->window
);
2085 void wxWindow::Lower()
2087 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2089 if (m_widget
) gdk_window_lower( m_widget
->window
);
2092 wxEvtHandler
*wxWindow::GetEventHandler() const
2094 return m_eventHandler
;
2097 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
2099 m_eventHandler
= handler
;
2102 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
2104 handler
->SetNextHandler(GetEventHandler());
2105 SetEventHandler(handler
);
2108 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
2110 if (GetEventHandler())
2112 wxEvtHandler
*handlerA
= GetEventHandler();
2113 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
2114 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
2115 SetEventHandler(handlerB
);
2119 return (wxEvtHandler
*) NULL
;
2125 return (wxEvtHandler
*) NULL
;
2128 wxValidator
*wxWindow::GetValidator()
2130 return m_windowValidator
;
2133 void wxWindow::SetValidator( const wxValidator
& validator
)
2135 if (m_windowValidator
) delete m_windowValidator
;
2136 m_windowValidator
= validator
.Clone();
2137 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
2140 void wxWindow::SetClientObject( wxClientData
*data
)
2142 if (m_clientObject
) delete m_clientObject
;
2143 m_clientObject
= data
;
2146 wxClientData
*wxWindow::GetClientObject()
2148 return m_clientObject
;
2151 void wxWindow::SetClientData( void *data
)
2153 m_clientData
= data
;
2156 void *wxWindow::GetClientData()
2158 return m_clientData
;
2161 bool wxWindow::IsBeingDeleted()
2166 void wxWindow::SetId( wxWindowID id
)
2171 wxWindowID
wxWindow::GetId() const
2176 void wxWindow::SetCursor( const wxCursor
&cursor
)
2178 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2182 if (cursor
== *m_cursor
) return;
2187 *m_cursor
= *wxSTANDARD_CURSOR
;
2190 if ((m_widget
) && (m_widget
->window
))
2191 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
2193 if ((m_wxwindow
) && (m_wxwindow
->window
))
2194 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
2197 void wxWindow::WarpPointer( int WXUNUSED(x
), int WXUNUSED(y
) )
2202 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2204 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2206 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2210 gdk_window_clear_area( m_wxwindow
->window
,
2224 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2226 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2230 GdkRectangle gdk_rect
;
2231 gdk_rect
.x
= rect
->x
;
2232 gdk_rect
.y
= rect
->y
;
2233 gdk_rect
.width
= rect
->width
;
2234 gdk_rect
.height
= rect
->height
;
2237 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2239 gtk_widget_draw( m_widget
, &gdk_rect
);
2243 wxRegion
wxWindow::GetUpdateRegion() const
2245 return m_updateRegion
;
2248 bool wxWindow::IsExposed( int x
, int y
) const
2250 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
2253 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
2255 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
2258 bool wxWindow::IsExposed( const wxPoint
& pt
) const
2260 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
2263 bool wxWindow::IsExposed( const wxRect
& rect
) const
2265 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
2268 void wxWindow::Clear()
2270 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2272 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
2275 wxColour
wxWindow::GetBackgroundColour() const
2277 return m_backgroundColour
;
2280 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
2282 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2284 if (m_backgroundColour
== colour
) return;
2286 m_backgroundColour
= colour
;
2287 if (!m_backgroundColour
.Ok()) return;
2291 GdkWindow
*window
= m_wxwindow
->window
;
2292 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2293 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2294 gdk_window_clear( window
);
2297 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2298 if (sysbg
.Red() == colour
.Red() &&
2299 sysbg
.Green() == colour
.Green() &&
2300 sysbg
.Blue() == colour
.Blue())
2302 m_backgroundColour
= wxNullColour
;
2304 m_backgroundColour
= sysbg
;
2312 wxColour
wxWindow::GetForegroundColour() const
2314 return m_foregroundColour
;
2317 void wxWindow::SetForegroundColour( const wxColour
&colour
)
2319 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2321 if (m_foregroundColour
== colour
) return;
2323 m_foregroundColour
= colour
;
2324 if (!m_foregroundColour
.Ok()) return;
2326 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2327 if (sysbg
.Red() == colour
.Red() &&
2328 sysbg
.Green() == colour
.Green() &&
2329 sysbg
.Blue() == colour
.Blue())
2331 m_backgroundColour
= wxNullColour
;
2333 m_backgroundColour
= sysbg
;
2341 GtkStyle
*wxWindow::GetWidgetStyle()
2343 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2347 gtk_widget_get_style( m_widget
) );
2349 return m_widgetStyle
;
2352 void wxWindow::SetWidgetStyle()
2354 GtkStyle
*style
= GetWidgetStyle();
2356 gdk_font_unref( style
->font
);
2357 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2359 if (m_foregroundColour
.Ok())
2361 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2362 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2363 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2364 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2367 if (m_backgroundColour
.Ok())
2369 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2370 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2371 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2372 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2373 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2374 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2375 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2376 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2377 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2381 void wxWindow::ApplyWidgetStyle()
2385 bool wxWindow::Validate()
2387 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2389 wxNode
*node
= m_children
.First();
2392 wxWindow
*child
= (wxWindow
*)node
->Data();
2393 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
2397 node
= node
->Next();
2402 bool wxWindow::TransferDataToWindow()
2404 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2406 wxNode
*node
= m_children
.First();
2409 wxWindow
*child
= (wxWindow
*)node
->Data();
2410 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
2411 !child
->GetValidator()->TransferToWindow() )
2413 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
2416 node
= node
->Next();
2421 bool wxWindow::TransferDataFromWindow()
2423 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2425 wxNode
*node
= m_children
.First();
2428 wxWindow
*child
= (wxWindow
*)node
->Data();
2429 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
2433 node
= node
->Next();
2438 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
2440 m_acceleratorTable
= accel
;
2443 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
2445 TransferDataToWindow();
2448 void wxWindow::InitDialog()
2450 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2452 wxInitDialogEvent
event(GetId());
2453 event
.SetEventObject( this );
2454 GetEventHandler()->ProcessEvent(event
);
2457 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2459 menu
->SetInvokingWindow( win
);
2460 wxNode
*node
= menu
->m_items
.First();
2463 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2464 if (menuitem
->IsSubMenu())
2466 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2468 node
= node
->Next();
2472 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
2474 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2476 wxCHECK_MSG( menu
!= NULL
, FALSE
, "invalid popup-menu" );
2478 SetInvokingWindow( menu
, this );
2480 GTK_MENU(menu
->m_menu
),
2481 (GtkWidget
*)NULL
, // parent menu shell
2482 (GtkWidget
*)NULL
, // parent menu item
2483 (GtkMenuPositionFunc
)NULL
,
2484 NULL
, // client data
2485 0, // button used to activate it
2486 0//gs_timeLastClick // the time of activation
2491 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2493 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2495 GtkWidget
*dnd_widget
= GetConnectWidget();
2497 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2499 if (m_dropTarget
) delete m_dropTarget
;
2500 m_dropTarget
= dropTarget
;
2502 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2505 wxDropTarget
*wxWindow::GetDropTarget() const
2507 return m_dropTarget
;
2510 GtkWidget
* wxWindow::GetConnectWidget()
2512 GtkWidget
*connect_widget
= m_widget
;
2513 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2515 return connect_widget
;
2518 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2520 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2521 return (window
== m_widget
->window
);
2524 void wxWindow::SetFont( const wxFont
&font
)
2526 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2528 if (((wxFont
*)&font
)->Ok())
2531 m_font
= *wxSWISS_FONT
;
2533 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2534 if (sysbg
.Red() == m_backgroundColour
.Red() &&
2535 sysbg
.Green() == m_backgroundColour
.Green() &&
2536 sysbg
.Blue() == m_backgroundColour
.Blue())
2538 m_backgroundColour
= wxNullColour
;
2540 m_backgroundColour
= sysbg
;
2548 void wxWindow::SetWindowStyleFlag( long flag
)
2550 m_windowStyle
= flag
;
2553 long wxWindow::GetWindowStyleFlag() const
2555 return m_windowStyle
;
2558 void wxWindow::CaptureMouse()
2560 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2562 wxCHECK_RET( g_capturing
== FALSE
, "CaptureMouse called twice" );
2564 GtkWidget
*connect_widget
= GetConnectWidget();
2565 gtk_grab_add( connect_widget
);
2566 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2568 (GDK_BUTTON_PRESS_MASK
|
2569 GDK_BUTTON_RELEASE_MASK
|
2570 GDK_POINTER_MOTION_MASK
),
2577 void wxWindow::ReleaseMouse()
2579 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2581 wxCHECK_RET( g_capturing
== TRUE
, "ReleaseMouse called twice" );
2583 GtkWidget
*connect_widget
= GetConnectWidget();
2584 gtk_grab_remove( connect_widget
);
2585 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2586 g_capturing
= FALSE
;
2589 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2593 wxString
wxWindow::GetTitle() const
2595 return (wxString
&)m_windowName
;
2598 wxString
wxWindow::GetLabel() const
2603 void wxWindow::SetName( const wxString
&name
)
2605 m_windowName
= name
;
2608 wxString
wxWindow::GetName() const
2610 return (wxString
&)m_windowName
;
2613 bool wxWindow::IsShown() const
2618 bool wxWindow::IsRetained()
2623 wxWindow
*wxWindow::FindWindow( long id
)
2625 if (id
== m_windowId
) return this;
2626 wxNode
*node
= m_children
.First();
2629 wxWindow
*child
= (wxWindow
*)node
->Data();
2630 wxWindow
*res
= child
->FindWindow( id
);
2631 if (res
) return res
;
2632 node
= node
->Next();
2634 return (wxWindow
*) NULL
;
2637 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2639 if (name
== m_windowName
) return this;
2640 wxNode
*node
= m_children
.First();
2643 wxWindow
*child
= (wxWindow
*)node
->Data();
2644 wxWindow
*res
= child
->FindWindow( name
);
2645 if (res
) return res
;
2646 node
= node
->Next();
2648 return (wxWindow
*) NULL
;
2651 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2652 int range
, bool refresh
)
2654 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2656 wxCHECK_RET( m_wxwindow
!= NULL
, "window needs client area for scrolling" );
2658 m_hasScrolling
= TRUE
;
2660 if (orient
== wxHORIZONTAL
)
2662 float fpos
= (float)pos
;
2663 float frange
= (float)range
;
2664 float fthumb
= (float)thumbVisible
;
2665 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2666 if (fpos
< 0.0) fpos
= 0.0;
2668 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2669 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2671 SetScrollPos( orient
, pos
, refresh
);
2675 m_oldHorizontalPos
= fpos
;
2677 m_hAdjust
->lower
= 0.0;
2678 m_hAdjust
->upper
= frange
;
2679 m_hAdjust
->value
= fpos
;
2680 m_hAdjust
->step_increment
= 1.0;
2681 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2682 m_hAdjust
->page_size
= fthumb
;
2686 float fpos
= (float)pos
;
2687 float frange
= (float)range
;
2688 float fthumb
= (float)thumbVisible
;
2689 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2690 if (fpos
< 0.0) fpos
= 0.0;
2692 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2693 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2695 SetScrollPos( orient
, pos
, refresh
);
2699 m_oldVerticalPos
= fpos
;
2701 m_vAdjust
->lower
= 0.0;
2702 m_vAdjust
->upper
= frange
;
2703 m_vAdjust
->value
= fpos
;
2704 m_vAdjust
->step_increment
= 1.0;
2705 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2706 m_vAdjust
->page_size
= fthumb
;
2709 if (m_wxwindow
->window
)
2711 if (orient
== wxHORIZONTAL
)
2712 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2714 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2716 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2720 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2722 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2724 wxCHECK_RET( m_wxwindow
!= NULL
, "window needs client area for scrolling" );
2726 if (orient
== wxHORIZONTAL
)
2728 float fpos
= (float)pos
;
2729 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2730 if (fpos
< 0.0) fpos
= 0.0;
2731 m_oldHorizontalPos
= fpos
;
2733 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2734 m_hAdjust
->value
= fpos
;
2738 float fpos
= (float)pos
;
2739 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2740 if (fpos
< 0.0) fpos
= 0.0;
2741 m_oldVerticalPos
= fpos
;
2743 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2744 m_vAdjust
->value
= fpos
;
2749 if (m_wxwindow
->window
)
2751 if (orient
== wxHORIZONTAL
)
2752 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2754 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2759 int wxWindow::GetScrollThumb( int orient
) const
2761 wxCHECK_MSG( m_widget
!= NULL
, 0, "invalid window" );
2763 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, "window needs client area for scrolling" );
2765 if (orient
== wxHORIZONTAL
)
2766 return (int)(m_hAdjust
->page_size
+0.5);
2768 return (int)(m_vAdjust
->page_size
+0.5);
2771 int wxWindow::GetScrollPos( int orient
) const
2773 wxCHECK_MSG( m_widget
!= NULL
, 0, "invalid window" );
2775 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, "window needs client area for scrolling" );
2777 if (orient
== wxHORIZONTAL
)
2778 return (int)(m_hAdjust
->value
+0.5);
2780 return (int)(m_vAdjust
->value
+0.5);
2783 int wxWindow::GetScrollRange( int orient
) const
2785 wxCHECK_MSG( m_widget
!= NULL
, 0, "invalid window" );
2787 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, "window needs client area for scrolling" );
2789 if (orient
== wxHORIZONTAL
)
2790 return (int)(m_hAdjust
->upper
+0.5);
2792 return (int)(m_vAdjust
->upper
+0.5);
2795 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2797 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2799 wxCHECK_RET( m_wxwindow
!= NULL
, "window needs client area for scrolling" );
2803 GetClientSize( &cw
, &ch
);
2805 int w
= cw
- abs(dx
);
2806 int h
= ch
- abs(dy
);
2807 if ((h
< 0) || (w
< 0))
2814 if (dx
< 0) s_x
= -dx
;
2815 if (dy
< 0) s_y
= -dy
;
2818 if (dx
> 0) d_x
= dx
;
2819 if (dy
> 0) d_y
= dy
;
2823 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2824 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2827 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2828 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2831 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2832 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2833 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2834 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2836 Refresh( TRUE
, &rect
);
2839 //-------------------------------------------------------------------------------------
2841 //-------------------------------------------------------------------------------------
2843 wxLayoutConstraints
*wxWindow::GetConstraints() const
2845 return m_constraints
;
2848 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2852 UnsetConstraints(m_constraints
);
2853 delete m_constraints
;
2855 m_constraints
= constraints
;
2858 // Make sure other windows know they're part of a 'meaningful relationship'
2859 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2860 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2861 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2862 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2863 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2864 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2865 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2866 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2867 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2868 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2869 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2870 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2871 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2872 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2873 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2874 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2880 void wxWindow::SetAutoLayout( bool autoLayout
)
2882 m_autoLayout
= autoLayout
;
2885 bool wxWindow::GetAutoLayout() const
2887 return m_autoLayout
;
2890 wxSizer
*wxWindow::GetSizer() const
2892 return m_windowSizer
;
2895 void wxWindow::SetSizerParent( wxWindow
*win
)
2897 m_sizerParent
= win
;
2900 wxWindow
*wxWindow::GetSizerParent() const
2902 return m_sizerParent
;
2905 // This removes any dangling pointers to this window
2906 // in other windows' constraintsInvolvedIn lists.
2907 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2911 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2912 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2913 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2914 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2915 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2916 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2917 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2918 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2919 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2920 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2921 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2922 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2923 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2924 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2925 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2926 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2930 // Back-pointer to other windows we're involved with, so if we delete
2931 // this window, we must delete any constraints we're involved with.
2932 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2934 if (!m_constraintsInvolvedIn
)
2935 m_constraintsInvolvedIn
= new wxList
;
2936 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2937 m_constraintsInvolvedIn
->Append(otherWin
);
2940 // REMOVE back-pointer to other windows we're involved with.
2941 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2943 if (m_constraintsInvolvedIn
)
2944 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2947 // Reset any constraints that mention this window
2948 void wxWindow::DeleteRelatedConstraints()
2950 if (m_constraintsInvolvedIn
)
2952 wxNode
*node
= m_constraintsInvolvedIn
->First();
2955 wxWindow
*win
= (wxWindow
*)node
->Data();
2956 wxNode
*next
= node
->Next();
2957 wxLayoutConstraints
*constr
= win
->GetConstraints();
2959 // Reset any constraints involving this window
2962 constr
->left
.ResetIfWin((wxWindow
*)this);
2963 constr
->top
.ResetIfWin((wxWindow
*)this);
2964 constr
->right
.ResetIfWin((wxWindow
*)this);
2965 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2966 constr
->width
.ResetIfWin((wxWindow
*)this);
2967 constr
->height
.ResetIfWin((wxWindow
*)this);
2968 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2969 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2974 delete m_constraintsInvolvedIn
;
2975 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2979 void wxWindow::SetSizer(wxSizer
*sizer
)
2981 m_windowSizer
= sizer
;
2983 sizer
->SetSizerParent((wxWindow
*)this);
2990 bool wxWindow::Layout()
2992 if (GetConstraints())
2995 GetClientSize(&w
, &h
);
2996 GetConstraints()->width
.SetValue(w
);
2997 GetConstraints()->height
.SetValue(h
);
3000 // If top level (one sizer), evaluate the sizer's constraints.
3004 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
3005 GetSizer()->LayoutPhase1(&noChanges
);
3006 GetSizer()->LayoutPhase2(&noChanges
);
3007 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
3012 // Otherwise, evaluate child constraints
3013 ResetConstraints(); // Mark all constraints as unevaluated
3014 DoPhase(1); // Just one phase need if no sizers involved
3016 SetConstraintSizes(); // Recursively set the real window sizes
3022 // Do a phase of evaluating constraints:
3023 // the default behaviour. wxSizers may do a similar
3024 // thing, but also impose their own 'constraints'
3025 // and order the evaluation differently.
3026 bool wxWindow::LayoutPhase1(int *noChanges
)
3028 wxLayoutConstraints
*constr
= GetConstraints();
3031 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
3037 bool wxWindow::LayoutPhase2(int *noChanges
)
3047 // Do a phase of evaluating child constraints
3048 bool wxWindow::DoPhase(int phase
)
3050 int noIterations
= 0;
3051 int maxIterations
= 500;
3055 while ((noChanges
> 0) && (noIterations
< maxIterations
))
3059 wxNode
*node
= m_children
.First();
3062 wxWindow
*child
= (wxWindow
*)node
->Data();
3063 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
3065 wxLayoutConstraints
*constr
= child
->GetConstraints();
3068 if (succeeded
.Member(child
))
3073 int tempNoChanges
= 0;
3074 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
3075 noChanges
+= tempNoChanges
;
3078 succeeded
.Append(child
);
3083 node
= node
->Next();
3090 void wxWindow::ResetConstraints()
3092 wxLayoutConstraints
*constr
= GetConstraints();
3095 constr
->left
.SetDone(FALSE
);
3096 constr
->top
.SetDone(FALSE
);
3097 constr
->right
.SetDone(FALSE
);
3098 constr
->bottom
.SetDone(FALSE
);
3099 constr
->width
.SetDone(FALSE
);
3100 constr
->height
.SetDone(FALSE
);
3101 constr
->centreX
.SetDone(FALSE
);
3102 constr
->centreY
.SetDone(FALSE
);
3104 wxNode
*node
= m_children
.First();
3107 wxWindow
*win
= (wxWindow
*)node
->Data();
3108 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
3109 win
->ResetConstraints();
3110 node
= node
->Next();
3114 // Need to distinguish between setting the 'fake' size for
3115 // windows and sizers, and setting the real values.
3116 void wxWindow::SetConstraintSizes(bool recurse
)
3118 wxLayoutConstraints
*constr
= GetConstraints();
3119 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
3120 constr
->width
.GetDone() && constr
->height
.GetDone())
3122 int x
= constr
->left
.GetValue();
3123 int y
= constr
->top
.GetValue();
3124 int w
= constr
->width
.GetValue();
3125 int h
= constr
->height
.GetValue();
3127 // If we don't want to resize this window, just move it...
3128 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
3129 (constr
->height
.GetRelationship() != wxAsIs
))
3131 // Calls Layout() recursively. AAAGH. How can we stop that.
3132 // Simply take Layout() out of non-top level OnSizes.
3133 SizerSetSize(x
, y
, w
, h
);
3142 char *windowClass
= this->GetClassInfo()->GetClassName();
3145 if (GetName() == "")
3146 winName
= "unnamed";
3148 winName
= GetName();
3149 wxLogDebug( "Constraint(s) not satisfied for window of type %s, name %s:\n",
3150 (const char *)windowClass
,
3151 (const char *)winName
);
3152 if (!constr
->left
.GetDone()) wxLogDebug( " unsatisfied 'left' constraint.\n" );
3153 if (!constr
->right
.GetDone()) wxLogDebug( " unsatisfied 'right' constraint.\n" );
3154 if (!constr
->width
.GetDone()) wxLogDebug( " unsatisfied 'width' constraint.\n" );
3155 if (!constr
->height
.GetDone()) wxLogDebug( " unsatisfied 'height' constraint.\n" );
3156 wxLogDebug( "Please check constraints: try adding AsIs() constraints.\n" );
3161 wxNode
*node
= m_children
.First();
3164 wxWindow
*win
= (wxWindow
*)node
->Data();
3165 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
3166 win
->SetConstraintSizes();
3167 node
= node
->Next();
3172 // This assumes that all sizers are 'on' the same
3173 // window, i.e. the parent of this window.
3174 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
3176 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
3177 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
3181 m_sizerParent
->GetPosition(&xp
, &yp
);
3182 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
3187 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
3191 TransformSizerToActual(&xx
, &yy
);
3192 SetSize(xx
, yy
, w
, h
);
3195 void wxWindow::SizerMove(int x
, int y
)
3199 TransformSizerToActual(&xx
, &yy
);
3203 // Only set the size/position of the constraint (if any)
3204 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
3206 wxLayoutConstraints
*constr
= GetConstraints();
3211 constr
->left
.SetValue(x
);
3212 constr
->left
.SetDone(TRUE
);
3216 constr
->top
.SetValue(y
);
3217 constr
->top
.SetDone(TRUE
);
3221 constr
->width
.SetValue(w
);
3222 constr
->width
.SetDone(TRUE
);
3226 constr
->height
.SetValue(h
);
3227 constr
->height
.SetDone(TRUE
);
3232 void wxWindow::MoveConstraint(int x
, int y
)
3234 wxLayoutConstraints
*constr
= GetConstraints();
3239 constr
->left
.SetValue(x
);
3240 constr
->left
.SetDone(TRUE
);
3244 constr
->top
.SetValue(y
);
3245 constr
->top
.SetDone(TRUE
);
3250 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
3252 wxLayoutConstraints
*constr
= GetConstraints();
3255 *w
= constr
->width
.GetValue();
3256 *h
= constr
->height
.GetValue();
3262 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
3264 wxLayoutConstraints
*constr
= GetConstraints();
3267 *w
= constr
->width
.GetValue();
3268 *h
= constr
->height
.GetValue();
3271 GetClientSize(w
, h
);
3274 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
3276 wxLayoutConstraints
*constr
= GetConstraints();
3279 *x
= constr
->left
.GetValue();
3280 *y
= constr
->top
.GetValue();
3286 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )