]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/window.cpp
6de4b2c637899fc19c423216ad10a0c422f93cb6
[wxWidgets.git] / src / gtk / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: window.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10
11 #ifdef __GNUG__
12 #pragma implementation "window.h"
13 #endif
14
15 #include "wx/defs.h"
16 #include "wx/window.h"
17 #include "wx/dc.h"
18 #include "wx/frame.h"
19 #include "wx/app.h"
20 #include "wx/layout.h"
21 #include "wx/utils.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
24 #include "wx/dcclient.h"
25 #include "wx/dnd.h"
26 #include "wx/menu.h"
27 #include "wx/statusbr.h"
28 #include "wx/intl.h"
29 #include "wx/settings.h"
30 #include "gdk/gdkprivate.h"
31 #include "gdk/gdkkeysyms.h"
32
33 #include <math.h>
34
35 //-----------------------------------------------------------------------------
36 // documentation on internals
37 //-----------------------------------------------------------------------------
38
39 /*
40 I have been asked several times about writing some documentation about
41 the GTK port of wxWindows, especially its internal structures. Obviously,
42 you cannot understand wxGTK without knowing a little about the GTK, but
43 some more information about what the wxWindow, which is the base class
44 for all other window classes, does seems required as well.
45
46 What does wxWindow do? It contains the common interface for the following
47 jobs of its descendants:
48
49 1) Define the rudimentary behaviour common to all window classes, such as
50 resizing, intercepting user input (so as to make it possible to use these
51 events for special purposes in a derived class), window names etc.
52
53 2) Provide the possibility to contain and manage children, if the derived
54 class is allowed to contain children, which holds true for those window
55 classes which do not display a native GTK widget. To name them, these
56 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
57 work classes are a special case and are handled a bit differently from
58 the rest. The same holds true for the wxNotebook class.
59
60 3) Provide the possibility to draw into a client area of a window. This,
61 too, only holds true for classes that do not display a native GTK widget
62 as above.
63
64 4) Provide the entire mechanism for scrolling widgets. This actual inter-
65 face for this is usually in wxScrolledWindow, but the GTK implementation
66 is in this class.
67
68 5) A multitude of helper or extra methods for special purposes, such as
69 Drag'n'Drop, managing validators etc.
70
71 Normally one might expect, that one wxWindows window would always correspond
72 to one GTK widget. Under GTK, there is no such allround widget that has all
73 the functionality. Moreover, the GTK defines a client area as a different
74 widget from the actual widget you are handling. Last but not least some
75 special classes (e.g. wxFrame) handle different categories of widgets and
76 still have the possibility to draw something in the client area.
77 It was therefore required to write a special purpose GTK widget, that would
78 represent a client area in the sense of wxWindows capable to do the jobs
79 2), 3) and 4). I have written this class and it resides in win_gtk.c of
80 this directory.
81
82 All windows must have a widget, with which they interact with other under-
83 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
84 thw wxWindow class has a member variable called m_widget which holds a
85 pointer to this widget. When the window class represents a GTK native widget,
86 this is (in most cases) the only GTK widget the class manages. E.g. the
87 wxStatitText class handles only a GtkLabel widget a pointer to which you
88 can find in m_widget (defined in wxWindow)
89
90 When the class has a client area for drawing into and for containing children
91 it has to handle the client area widget (of the type GtkMyFixed, defined in
92 win_gtk.c), but there could be any number of widgets, handled by a class
93 The common rule for all windows is only, that the widget that interacts with
94 the rest of GTK must be referenced in m_widget and all other widgets must be
95 children of this widget on the GTK level. The top-most widget, which also
96 represents the client area, must be in the m_wxwindow field and must be of
97 the type GtkMyFixed.
98
99 As I said, the window classes that display a GTK native widget only have
100 one widget, so in the case of e.g. the wxButton class m_widget holds a
101 pointer to a GtkButton widget. But windows with client areas (for drawing
102 and children) have a m_widget field that is a pointer to a GtkScrolled-
103 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
104 one is (in the GTK sense) a child of the GtkScrolledWindow.
105
106 If the m_wxwindow field is set, then all input to this widget is inter-
107 cepted and sent to the wxWindows class. If not, all input to the widget
108 that gets pointed to by m_widget gets intercepted and sent to the class.
109
110 */
111
112 //-------------------------------------------------------------------------
113 // conditional compilation
114 //-------------------------------------------------------------------------
115
116 #if (GTK_MINOR_VERSION == 1)
117 #if (GTK_MICRO_VERSION >= 5)
118 #define NEW_GTK_SCROLL_CODE
119 #endif
120 #endif
121
122 //-----------------------------------------------------------------------------
123 // data
124 //-----------------------------------------------------------------------------
125
126 extern wxList wxPendingDelete;
127 extern wxList wxTopLevelWindows;
128 extern bool g_blockEventsOnDrag;
129 extern bool g_blockEventsOnScroll;
130 static bool g_capturing = FALSE;
131
132 // hack: we need something to pass to gtk_menu_popup, so we store the time of
133 // the last click here
134 static guint32 gs_timeLastClick = 0;
135
136 //-----------------------------------------------------------------------------
137 // "expose_event" (of m_wxwindow, not of m_widget)
138 //-----------------------------------------------------------------------------
139
140 static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
141 {
142 if (!win->HasVMT()) return;
143
144 win->m_updateRegion.Union( gdk_event->area.x,
145 gdk_event->area.y,
146 gdk_event->area.width,
147 gdk_event->area.height );
148
149 if (gdk_event->count > 0) return;
150
151 /*
152 printf( "OnExpose from " );
153 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
154 printf( win->GetClassInfo()->GetClassName() );
155 printf( ".\n" );
156 */
157
158 wxPaintEvent event( win->GetId() );
159 event.SetEventObject( win );
160 win->GetEventHandler()->ProcessEvent( event );
161
162 win->m_updateRegion.Clear();
163 }
164
165 //-----------------------------------------------------------------------------
166 // "draw" (of m_wxwindow, not of m_widget)
167 //-----------------------------------------------------------------------------
168
169 static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxWindow *win )
170 {
171 if (!win->HasVMT()) return;
172
173 win->m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
174
175 wxPaintEvent event( win->GetId() );
176 event.SetEventObject( win );
177 win->GetEventHandler()->ProcessEvent( event );
178
179 win->m_updateRegion.Clear();
180 }
181
182 //-----------------------------------------------------------------------------
183 // "key_press_event"
184 //-----------------------------------------------------------------------------
185
186 static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
187 {
188 if (!win->HasVMT()) return FALSE;
189 if (g_blockEventsOnDrag) return FALSE;
190
191 /*
192 printf( "OnKeyPress from " );
193 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
194 printf( win->GetClassInfo()->GetClassName() );
195 printf( ".\n" );
196 */
197
198 long key_code = 0;
199 switch (gdk_event->keyval)
200 {
201 case GDK_BackSpace: key_code = WXK_BACK; break;
202 case GDK_Tab: key_code = WXK_TAB; break;
203 case GDK_Linefeed: key_code = WXK_RETURN; break;
204 case GDK_Clear: key_code = WXK_CLEAR; break;
205 case GDK_Return: key_code = WXK_RETURN; break;
206 case GDK_Pause: key_code = WXK_PAUSE; break;
207 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
208 case GDK_Escape: key_code = WXK_ESCAPE; break;
209 case GDK_Delete: key_code = WXK_DELETE; break;
210 case GDK_Home: key_code = WXK_HOME; break;
211 case GDK_Left: key_code = WXK_LEFT; break;
212 case GDK_Up: key_code = WXK_UP; break;
213 case GDK_Right: key_code = WXK_RIGHT; break;
214 case GDK_Down: key_code = WXK_DOWN; break;
215 case GDK_Prior: key_code = WXK_PRIOR; break;
216 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
217 case GDK_Next: key_code = WXK_NEXT; break;
218 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
219 case GDK_End: key_code = WXK_END; break;
220 case GDK_Begin: key_code = WXK_HOME; break;
221 case GDK_Select: key_code = WXK_SELECT; break;
222 case GDK_Print: key_code = WXK_PRINT; break;
223 case GDK_Execute: key_code = WXK_EXECUTE; break;
224 case GDK_Insert: key_code = WXK_INSERT; break;
225 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
226 case GDK_KP_Tab: key_code = WXK_TAB; break;
227 case GDK_KP_Enter: key_code = WXK_RETURN; break;
228 case GDK_KP_Home: key_code = WXK_HOME; break;
229 case GDK_KP_Left: key_code = WXK_LEFT; break;
230 case GDK_KP_Up: key_code = WXK_UP; break;
231 case GDK_KP_Right: key_code = WXK_RIGHT; break;
232 case GDK_KP_Down: key_code = WXK_DOWN; break;
233 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
234 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
235 case GDK_KP_Next: key_code = WXK_NEXT; break;
236 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
237 case GDK_KP_End: key_code = WXK_END; break;
238 case GDK_KP_Begin: key_code = WXK_HOME; break;
239 case GDK_KP_Insert: key_code = WXK_INSERT; break;
240 case GDK_KP_Delete: key_code = WXK_DELETE; break;
241 case GDK_KP_Multiply: key_code = WXK_MULTIPLY; break;
242 case GDK_KP_Add: key_code = WXK_ADD; break;
243 case GDK_KP_Separator: key_code = WXK_SEPARATOR; break;
244 case GDK_KP_Subtract: key_code = WXK_SUBTRACT; break;
245 case GDK_KP_Decimal: key_code = WXK_DECIMAL; break;
246 case GDK_KP_Divide: key_code = WXK_DIVIDE; break;
247 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
248 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
249 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
250 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
251 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
252 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
253 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
254 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
255 case GDK_KP_8: key_code = WXK_NUMPAD7; break;
256 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
257 case GDK_F1: key_code = WXK_F1; break;
258 case GDK_F2: key_code = WXK_F2; break;
259 case GDK_F3: key_code = WXK_F3; break;
260 case GDK_F4: key_code = WXK_F4; break;
261 case GDK_F5: key_code = WXK_F5; break;
262 case GDK_F6: key_code = WXK_F6; break;
263 case GDK_F7: key_code = WXK_F7; break;
264 case GDK_F8: key_code = WXK_F8; break;
265 case GDK_F9: key_code = WXK_F9; break;
266 case GDK_F10: key_code = WXK_F10; break;
267 case GDK_F11: key_code = WXK_F11; break;
268 case GDK_F12: key_code = WXK_F12; break;
269 default:
270 {
271 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
272 key_code = gdk_event->keyval;
273 }
274 }
275
276 if (!key_code) return FALSE;
277
278 wxKeyEvent event( wxEVT_CHAR );
279 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
280 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
281 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
282 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
283 event.m_keyCode = key_code;
284 event.m_x = 0;
285 event.m_y = 0;
286 event.SetEventObject( win );
287
288 bool ret = win->GetEventHandler()->ProcessEvent( event );
289
290 if (!ret)
291 {
292 wxWindow *ancestor = win;
293 while (ancestor)
294 {
295 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
296 if (command != -1)
297 {
298 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
299 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
300 break;
301 }
302 ancestor = ancestor->GetParent();
303 }
304 }
305
306 if (ret)
307 {
308 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
309 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
310 }
311
312 return ret;
313 }
314
315 //-----------------------------------------------------------------------------
316 // "button_press_event"
317 //-----------------------------------------------------------------------------
318
319 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
320 {
321 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
322
323 if (g_blockEventsOnDrag) return TRUE;
324 if (g_blockEventsOnScroll) return TRUE;
325
326 if (win->m_wxwindow)
327 {
328 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
329 {
330 gtk_widget_grab_focus (win->m_wxwindow);
331
332 /*
333 printf( "GrabFocus from " );
334 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
335 printf( win->GetClassInfo()->GetClassName() );
336 printf( ".\n" );
337 */
338
339 }
340 }
341
342 if (!win->HasVMT()) return TRUE;
343
344 /*
345 printf( "OnButtonPress from " );
346 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
347 printf( win->GetClassInfo()->GetClassName() );
348 printf( ".\n" );
349 */
350
351 wxEventType event_type = wxEVT_LEFT_DOWN;
352
353 if (gdk_event->button == 1)
354 {
355 switch (gdk_event->type)
356 {
357 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
358 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
359 default: break;
360 }
361 }
362 else if (gdk_event->button == 2)
363 {
364 switch (gdk_event->type)
365 {
366 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
367 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
368 default: break;
369 }
370 }
371 else if (gdk_event->button == 3)
372 {
373 switch (gdk_event->type)
374 {
375 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
376 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
377 default: break;
378 }
379 }
380
381 wxMouseEvent event( event_type );
382 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
383 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
384 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
385 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
386 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
387 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
388 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
389
390 event.m_x = (long)gdk_event->x;
391 event.m_y = (long)gdk_event->y;
392
393 // Some control don't have their own X window and thus cannot get
394 // any events.
395
396 if (!g_capturing)
397 {
398 wxNode *node = win->GetChildren()->First();
399 while (node)
400 {
401 wxWindow *child = (wxWindow*)node->Data();
402 if ((child->m_x <= event.m_x) &&
403 (child->m_y <= event.m_y) &&
404 (child->m_x+child->m_width >= event.m_x) &&
405 (child->m_y+child->m_height >= event.m_y))
406 {
407 win = child;
408 event.m_x -= child->m_x;
409 event.m_y -= child->m_y;
410 break;
411 }
412 node = node->Next();
413 }
414 }
415
416 event.SetEventObject( win );
417
418 gs_timeLastClick = gdk_event->time;
419
420 if (win->GetEventHandler()->ProcessEvent( event ))
421 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
422
423 return TRUE;
424 }
425
426 //-----------------------------------------------------------------------------
427 // "button_release_event"
428 //-----------------------------------------------------------------------------
429
430 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
431 {
432 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
433
434 if (g_blockEventsOnDrag) return TRUE;
435 if (g_blockEventsOnScroll) return TRUE;
436
437 if (!win->HasVMT()) return TRUE;
438
439 /*
440 printf( "OnButtonRelease from " );
441 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
442 printf( win->GetClassInfo()->GetClassName() );
443 printf( ".\n" );
444 */
445
446 wxEventType event_type = wxEVT_NULL;
447
448 switch (gdk_event->button)
449 {
450 case 1: event_type = wxEVT_LEFT_UP; break;
451 case 2: event_type = wxEVT_MIDDLE_UP; break;
452 case 3: event_type = wxEVT_RIGHT_UP; break;
453 }
454
455 wxMouseEvent event( event_type );
456 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
457 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
458 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
459 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
460 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
461 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
462 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
463 event.m_x = (long)gdk_event->x;
464 event.m_y = (long)gdk_event->y;
465
466 // Some control don't have their own X window and thus cannot get
467 // any events.
468
469 if (!g_capturing)
470 {
471 wxNode *node = win->GetChildren()->First();
472 while (node)
473 {
474 wxWindow *child = (wxWindow*)node->Data();
475 if ((child->m_x <= event.m_x) &&
476 (child->m_y <= event.m_y) &&
477 (child->m_x+child->m_width >= event.m_x) &&
478 (child->m_y+child->m_height >= event.m_y))
479 {
480 win = child;
481 event.m_x -= child->m_x;
482 event.m_y -= child->m_y;
483 break;
484 }
485 node = node->Next();
486 }
487 }
488
489 event.SetEventObject( win );
490
491 if (win->GetEventHandler()->ProcessEvent( event ))
492 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
493
494 return TRUE;
495 }
496
497 //-----------------------------------------------------------------------------
498 // "motion_notify_event"
499 //-----------------------------------------------------------------------------
500
501 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
502 {
503 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
504
505 if (g_blockEventsOnDrag) return TRUE;
506 if (g_blockEventsOnScroll) return TRUE;
507
508 if (!win->HasVMT()) return TRUE;
509
510 /*
511 printf( "OnMotion from " );
512 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
513 printf( win->GetClassInfo()->GetClassName() );
514 printf( ".\n" );
515 */
516
517 wxMouseEvent event( wxEVT_MOTION );
518 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
519 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
520 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
521 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
522 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
523 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
524 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
525
526 event.m_x = (long)gdk_event->x;
527 event.m_y = (long)gdk_event->y;
528
529 // Some control don't have their own X window and thus cannot get
530 // any events.
531
532 if (!g_capturing)
533 {
534 wxNode *node = win->GetChildren()->First();
535 while (node)
536 {
537 wxWindow *child = (wxWindow*)node->Data();
538 if ((child->m_x <= event.m_x) &&
539 (child->m_y <= event.m_y) &&
540 (child->m_x+child->m_width >= event.m_x) &&
541 (child->m_y+child->m_height >= event.m_y))
542 {
543 win = child;
544 event.m_x -= child->m_x;
545 event.m_y -= child->m_y;
546 break;
547 }
548 node = node->Next();
549 }
550 }
551
552 event.SetEventObject( win );
553
554 if (win->GetEventHandler()->ProcessEvent( event ))
555 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
556
557 return TRUE;
558 }
559
560 //-----------------------------------------------------------------------------
561 // "focus_in_event"
562 //-----------------------------------------------------------------------------
563
564 static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
565 {
566 if (g_blockEventsOnDrag) return TRUE;
567 if (win->m_wxwindow)
568 {
569 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
570 {
571 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
572 /*
573 printf( "SetFocus flag from " );
574 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
575 printf( win->GetClassInfo()->GetClassName() );
576 printf( ".\n" );
577 */
578 }
579 }
580
581 if (!win->HasVMT()) return TRUE;
582
583 /*
584 printf( "OnSetFocus from " );
585 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
586 printf( win->GetClassInfo()->GetClassName() );
587 printf( " " );
588 printf( WXSTRINGCAST win->GetLabel() );
589 printf( ".\n" );
590 */
591
592 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
593 event.SetEventObject( win );
594
595 if (win->GetEventHandler()->ProcessEvent( event ))
596 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
597
598 return TRUE;
599 }
600
601 //-----------------------------------------------------------------------------
602 // "focus_out_event"
603 //-----------------------------------------------------------------------------
604
605 static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
606 {
607 if (g_blockEventsOnDrag) return TRUE;
608 if (win->m_wxwindow)
609 {
610 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
611 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
612 }
613
614 if (!win->HasVMT()) return TRUE;
615
616 /*
617 printf( "OnKillFocus from " );
618 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
619 printf( win->GetClassInfo()->GetClassName() );
620 printf( ".\n" );
621 */
622
623 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
624 event.SetEventObject( win );
625
626 if (win->GetEventHandler()->ProcessEvent( event ))
627 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
628
629 return TRUE;
630 }
631
632 //-----------------------------------------------------------------------------
633 // "enter_notify_event"
634 //-----------------------------------------------------------------------------
635
636 static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
637 {
638 if (widget->window != gdk_event->window) return TRUE;
639
640 if (g_blockEventsOnDrag) return TRUE;
641
642 if (!win->HasVMT()) return TRUE;
643
644 /*
645 printf( "OnEnter from " );
646 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
647 printf( win->GetClassInfo()->GetClassName() );
648 printf( ".\n" );
649 */
650
651 if ((widget->window) && (win->m_cursor))
652 gdk_window_set_cursor( widget->window, win->m_cursor->GetCursor() );
653
654 wxMouseEvent event( wxEVT_ENTER_WINDOW );
655 event.SetEventObject( win );
656
657 if (win->GetEventHandler()->ProcessEvent( event ))
658 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
659
660 return TRUE;
661 }
662
663 //-----------------------------------------------------------------------------
664 // "leave_notify_event"
665 //-----------------------------------------------------------------------------
666
667 static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
668 {
669 if (widget->window != gdk_event->window) return TRUE;
670
671 if (g_blockEventsOnDrag) return TRUE;
672
673 if (!win->HasVMT()) return TRUE;
674
675 /*
676 printf( "OnLeave from " );
677 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
678 printf( win->GetClassInfo()->GetClassName() );
679 printf( ".\n" );
680 */
681
682 if ((widget->window) && (win->m_cursor))
683 gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
684
685 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
686 event.SetEventObject( win );
687
688 if (win->GetEventHandler()->ProcessEvent( event ))
689 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
690
691 return TRUE;
692 }
693
694 //-----------------------------------------------------------------------------
695 // "value_changed" from m_vAdjust
696 //-----------------------------------------------------------------------------
697
698 static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
699 {
700 if (g_blockEventsOnDrag) return;
701
702 /*
703 printf( "OnVScroll from " );
704 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
705 printf( win->GetClassInfo()->GetClassName() );
706 printf( ".\n" );
707 */
708
709 if (!win->HasVMT()) return;
710
711 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
712 if (fabs(diff) < 0.2) return;
713
714 wxEventType command = wxEVT_NULL;
715
716 float line_step = win->m_vAdjust->step_increment;
717 float page_step = win->m_vAdjust->page_increment;
718
719 if (win->m_isScrolling)
720 {
721 command = wxEVT_SCROLL_THUMBTRACK;
722 }
723 else
724 {
725 if (fabs(win->m_vAdjust->value-win->m_vAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
726 else if (fabs(win->m_vAdjust->value-win->m_vAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
727 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
728 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
729 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
730 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
731 else command = wxEVT_SCROLL_THUMBTRACK;
732 }
733
734 int value = (int)(win->m_vAdjust->value+0.5);
735
736 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
737 event.SetEventObject( win );
738 win->GetEventHandler()->ProcessEvent( event );
739 }
740
741 //-----------------------------------------------------------------------------
742 // "value_changed" from m_hAdjust
743 //-----------------------------------------------------------------------------
744
745 static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
746 {
747 if (g_blockEventsOnDrag) return;
748
749 /*
750 printf( "OnHScroll from " );
751 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
752 printf( win->GetClassInfo()->GetClassName() );
753 printf( ".\n" );
754 */
755
756 if (!win->HasVMT()) return;
757
758 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
759 if (fabs(diff) < 0.2) return;
760
761 wxEventType command = wxEVT_NULL;
762
763 float line_step = win->m_hAdjust->step_increment;
764 float page_step = win->m_hAdjust->page_increment;
765
766 if (win->m_isScrolling)
767 {
768 command = wxEVT_SCROLL_THUMBTRACK;
769 }
770 else
771 {
772 if (fabs(win->m_hAdjust->value-win->m_hAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
773 else if (fabs(win->m_hAdjust->value-win->m_hAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
774 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
775 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
776 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
777 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
778 else command = wxEVT_SCROLL_THUMBTRACK;
779 }
780
781 int value = (int)(win->m_hAdjust->value+0.5);
782
783 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
784 event.SetEventObject( win );
785 win->GetEventHandler()->ProcessEvent( event );
786 }
787
788 //-----------------------------------------------------------------------------
789 // "changed" from m_vAdjust
790 //-----------------------------------------------------------------------------
791
792 static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
793 {
794 if (g_blockEventsOnDrag) return;
795
796 /*
797 printf( "OnVScroll change from " );
798 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
799 printf( win->GetClassInfo()->GetClassName() );
800 printf( ".\n" );
801 */
802
803 if (!win->HasVMT()) return;
804
805 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
806 int value = (int)(win->m_vAdjust->value+0.5);
807
808 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
809 event.SetEventObject( win );
810 win->GetEventHandler()->ProcessEvent( event );
811 }
812
813 //-----------------------------------------------------------------------------
814 // "changed" from m_hAdjust
815 //-----------------------------------------------------------------------------
816
817 static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
818 {
819 if (g_blockEventsOnDrag) return;
820
821 /*
822 printf( "OnHScroll change from " );
823 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
824 printf( win->GetClassInfo()->GetClassName() );
825 printf( ".\n" );
826 */
827
828 if (!win->HasVMT()) return;
829
830 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
831 int value = (int)(win->m_hAdjust->value+0.5);
832
833 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
834 event.SetEventObject( win );
835 win->GetEventHandler()->ProcessEvent( event );
836 }
837
838 //-----------------------------------------------------------------------------
839 // "button_press_event" from scrollbar
840 //-----------------------------------------------------------------------------
841
842 static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
843 GdkEventButton *WXUNUSED(gdk_event),
844 wxWindow *win )
845 {
846 // if (gdk_event->window != widget->slider) return FALSE;
847
848 win->m_isScrolling = TRUE;
849 g_blockEventsOnScroll = TRUE;
850
851 return FALSE;
852 }
853
854 //-----------------------------------------------------------------------------
855 // "button_release_event" from scrollbar
856 //-----------------------------------------------------------------------------
857
858 static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
859 GdkEventButton *WXUNUSED(gdk_event),
860 wxWindow *win )
861 {
862
863 // don't test here as we can reelase the mouse while being over
864 // a different window then the slider
865 //
866 // if (gdk_event->window != widget->slider) return FALSE;
867
868 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(win->m_widget);
869
870 if (widget == GTK_RANGE(s_window->vscrollbar))
871 gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
872 else
873 gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
874
875 win->m_isScrolling = FALSE;
876 g_blockEventsOnScroll = FALSE;
877
878 return FALSE;
879 }
880
881 //-----------------------------------------------------------------------------
882 // InsertChild for wxWindow.
883 //-----------------------------------------------------------------------------
884
885 // Callback for wxWindow. This very strange beast has to be used because
886 // C++ has no virtual methods in a constructor. We have to emulate a
887 // virtual function here as wxNotebook requires a different way to insert
888 // a child in it. I had opted for creating a wxNotebookPage window class
889 // which would have made this superflouus (such in the MDI window system),
890 // but no-one is listening to me...
891
892 static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
893 {
894 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
895 GTK_WIDGET(child->m_widget),
896 child->m_x,
897 child->m_y );
898
899 gtk_widget_set_usize( GTK_WIDGET(child->m_widget),
900 child->m_width,
901 child->m_height );
902 }
903
904 //-----------------------------------------------------------------------------
905 // wxWindow
906 //-----------------------------------------------------------------------------
907
908 IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler)
909
910 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
911 EVT_SIZE(wxWindow::OnSize)
912 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
913 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
914 EVT_IDLE(wxWindow::OnIdle)
915 END_EVENT_TABLE()
916
917 wxWindow::wxWindow()
918 {
919 m_widget = (GtkWidget *) NULL;
920 m_wxwindow = (GtkWidget *) NULL;
921 m_parent = (wxWindow *) NULL;
922 m_children.DeleteContents( FALSE );
923
924 m_x = 0;
925 m_y = 0;
926 m_width = 0;
927 m_height = 0;
928 m_minWidth = -1;
929 m_minHeight = -1;
930 m_maxWidth = -1;
931 m_maxHeight = -1;
932
933 m_retCode = 0;
934
935 m_eventHandler = this;
936 m_windowValidator = (wxValidator *) NULL;
937
938 m_windowId = -1;
939
940 m_cursor = (wxCursor *) NULL;
941 m_font = *wxSWISS_FONT;
942 m_windowStyle = 0;
943 m_windowName = "noname";
944
945 m_constraints = (wxLayoutConstraints *) NULL;
946 m_constraintsInvolvedIn = (wxList *) NULL;
947 m_windowSizer = (wxSizer *) NULL;
948 m_sizerParent = (wxWindow *) NULL;
949 m_autoLayout = FALSE;
950
951 m_sizeSet = FALSE;
952 m_hasVMT = FALSE;
953 m_needParent = TRUE;
954
955 m_hasScrolling = FALSE;
956 m_isScrolling = FALSE;
957 m_hAdjust = (GtkAdjustment*) NULL;
958 m_vAdjust = (GtkAdjustment*) NULL;
959 m_oldHorizontalPos = 0.0;
960 m_oldVerticalPos = 0.0;
961
962 m_isShown = FALSE;
963 m_isEnabled = TRUE;
964
965 m_dropTarget = (wxDropTarget*) NULL;
966 m_resizing = FALSE;
967 m_scrollGC = (GdkGC*) NULL;
968 m_widgetStyle = (GtkStyle*) NULL;
969
970 m_insertCallback = wxInsertChildInWindow;
971
972 m_clientObject = (wxClientData*) NULL;
973 m_clientData = NULL;
974 }
975
976 wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
977 const wxPoint &pos, const wxSize &size,
978 long style, const wxString &name )
979 {
980 m_insertCallback = wxInsertChildInWindow;
981 Create( parent, id, pos, size, style, name );
982 }
983
984 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
985 const wxPoint &pos, const wxSize &size,
986 long style, const wxString &name )
987 {
988 m_isShown = FALSE;
989 m_isEnabled = TRUE;
990 m_needParent = TRUE;
991
992 PreCreation( parent, id, pos, size, style, name );
993
994 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
995 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
996
997 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
998
999 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1000 scroll_class->scrollbar_spacing = 0;
1001
1002 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
1003
1004 m_oldHorizontalPos = 0.0;
1005 m_oldVerticalPos = 0.0;
1006
1007 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
1008 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
1009
1010 m_wxwindow = gtk_myfixed_new();
1011
1012 #ifdef NEW_GTK_SCROLL_CODE
1013 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget), m_wxwindow );
1014 GtkViewport *viewport = GTK_VIEWPORT(s_window->child);
1015 #else
1016 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
1017 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
1018 #endif
1019
1020 if (m_windowStyle & wxRAISED_BORDER)
1021 {
1022 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1023 }
1024 else if (m_windowStyle & wxSUNKEN_BORDER)
1025 {
1026 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1027 }
1028 else
1029 {
1030 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1031 }
1032
1033 if (m_windowStyle & wxTAB_TRAVERSAL == wxTAB_TRAVERSAL)
1034 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1035 else
1036 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1037
1038 // shut the viewport up
1039 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1040 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1041
1042 // I _really_ don't want scrollbars in the beginning
1043 m_vAdjust->lower = 0.0;
1044 m_vAdjust->upper = 1.0;
1045 m_vAdjust->value = 0.0;
1046 m_vAdjust->step_increment = 1.0;
1047 m_vAdjust->page_increment = 1.0;
1048 m_vAdjust->page_size = 5.0;
1049 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1050 m_hAdjust->lower = 0.0;
1051 m_hAdjust->upper = 1.0;
1052 m_hAdjust->value = 0.0;
1053 m_hAdjust->step_increment = 1.0;
1054 m_hAdjust->page_increment = 1.0;
1055 m_hAdjust->page_size = 5.0;
1056 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1057
1058 // these handlers block mouse events to any window during scrolling
1059 // such as motion events and prevent GTK and wxWindows from fighting
1060 // over where the slider should be
1061
1062 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_press_event",
1063 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1064
1065 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
1066 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1067
1068 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
1069 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1070
1071 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
1072 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1073
1074 // these handers het notified when screen updates are required either when
1075 // scrolling or when the window size (and therefore scrollbar configuration)
1076 // has changed
1077
1078 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1079 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1080 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1081 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1082
1083 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1084 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1085 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1086 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1087
1088 gtk_widget_show( m_wxwindow );
1089
1090 if (m_parent) m_parent->AddChild( this );
1091
1092 (m_parent->m_insertCallback)( m_parent, this );
1093
1094 PostCreation();
1095
1096 Show( TRUE );
1097
1098 return TRUE;
1099 }
1100
1101 wxWindow::~wxWindow()
1102 {
1103 m_hasVMT = FALSE;
1104
1105 if (m_dropTarget) delete m_dropTarget;
1106
1107 if (m_parent) m_parent->RemoveChild( this );
1108 if (m_widget) Show( FALSE );
1109
1110 DestroyChildren();
1111
1112 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
1113
1114 if (m_scrollGC) gdk_gc_unref( m_scrollGC );
1115
1116 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
1117
1118 if (m_widget) gtk_widget_destroy( m_widget );
1119
1120 if (m_cursor) delete m_cursor;
1121
1122 DeleteRelatedConstraints();
1123 if (m_constraints)
1124 {
1125 // This removes any dangling pointers to this window
1126 // in other windows' constraintsInvolvedIn lists.
1127 UnsetConstraints(m_constraints);
1128 delete m_constraints;
1129 m_constraints = (wxLayoutConstraints *) NULL;
1130 }
1131 if (m_windowSizer)
1132 {
1133 delete m_windowSizer;
1134 m_windowSizer = (wxSizer *) NULL;
1135 }
1136 // If this is a child of a sizer, remove self from parent
1137 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
1138
1139 // Just in case the window has been Closed, but
1140 // we're then deleting immediately: don't leave
1141 // dangling pointers.
1142 wxPendingDelete.DeleteObject(this);
1143
1144 // Just in case we've loaded a top-level window via
1145 // wxWindow::LoadNativeDialog but we weren't a dialog
1146 // class
1147 wxTopLevelWindows.DeleteObject(this);
1148
1149 if (m_windowValidator) delete m_windowValidator;
1150
1151 if (m_clientObject) delete m_clientObject;
1152 }
1153
1154 void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1155 const wxPoint &pos, const wxSize &size,
1156 long style, const wxString &name )
1157 {
1158 if (m_needParent && (parent == NULL))
1159 wxFatalError( "Need complete parent.", name );
1160
1161 m_widget = (GtkWidget*) NULL;
1162 m_wxwindow = (GtkWidget*) NULL;
1163 m_hasVMT = FALSE;
1164 m_parent = parent;
1165 m_children.DeleteContents( FALSE );
1166
1167 m_width = size.x;
1168 if (m_width == -1) m_width = 20;
1169 m_height = size.y;
1170 if (m_height == -1) m_height = 20;
1171
1172 m_x = (int)pos.x;
1173 m_y = (int)pos.y;
1174
1175 if (!m_needParent) // some reasonable defaults
1176 {
1177 if (m_x == -1)
1178 {
1179 m_x = (gdk_screen_width () - m_width) / 2;
1180 if (m_x < 10) m_x = 10;
1181 }
1182 if (m_y == -1)
1183 {
1184 m_y = (gdk_screen_height () - m_height) / 2;
1185 if (m_y < 10) m_y = 10;
1186 }
1187 }
1188
1189 m_minWidth = -1;
1190 m_minHeight = -1;
1191 m_maxWidth = -1;
1192 m_maxHeight = -1;
1193
1194 m_retCode = 0;
1195
1196 m_eventHandler = this;
1197
1198 m_windowId = id == -1 ? wxNewId() : id;
1199
1200 m_sizeSet = FALSE;
1201
1202 m_cursor = new wxCursor( wxCURSOR_ARROW );
1203 m_font = *wxSWISS_FONT;
1204 // m_backgroundColour = wxWHITE;
1205 // m_foregroundColour = wxBLACK;
1206 m_windowStyle = style;
1207 m_windowName = name;
1208
1209 m_constraints = (wxLayoutConstraints *) NULL;
1210 m_constraintsInvolvedIn = (wxList *) NULL;
1211 m_windowSizer = (wxSizer *) NULL;
1212 m_sizerParent = (wxWindow *) NULL;
1213 m_autoLayout = FALSE;
1214
1215 m_hasScrolling = FALSE;
1216 m_isScrolling = FALSE;
1217 m_hAdjust = (GtkAdjustment *) NULL;
1218 m_vAdjust = (GtkAdjustment *) NULL;
1219 m_oldHorizontalPos = 0.0;
1220 m_oldVerticalPos = 0.0;
1221
1222 m_isShown = FALSE;
1223 m_isEnabled = TRUE;
1224
1225 m_dropTarget = (wxDropTarget *) NULL;
1226 m_resizing = FALSE;
1227 m_windowValidator = (wxValidator *) NULL;
1228 m_scrollGC = (GdkGC*) NULL;
1229 m_widgetStyle = (GtkStyle*) NULL;
1230
1231 m_clientObject = (wxClientData*)NULL;
1232 m_clientData = NULL;
1233 }
1234
1235 void wxWindow::PostCreation()
1236 {
1237 if (m_wxwindow)
1238 {
1239 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1240 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
1241
1242 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1243 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
1244 }
1245
1246 ConnectWidget( GetConnectWidget() );
1247
1248 if (m_widget && m_parent) gtk_widget_realize( m_widget );
1249
1250 if (m_wxwindow) gtk_widget_realize( m_wxwindow );
1251
1252 SetCursor( *wxSTANDARD_CURSOR );
1253
1254 m_hasVMT = TRUE;
1255 }
1256
1257 void wxWindow::ConnectWidget( GtkWidget *widget )
1258 {
1259 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1260 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
1261
1262 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1263 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
1264
1265 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1266 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
1267
1268 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1269 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
1270
1271 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1272 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
1273
1274 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1275 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
1276
1277 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1278 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
1279
1280 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1281 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
1282 }
1283
1284 bool wxWindow::HasVMT()
1285 {
1286 return m_hasVMT;
1287 }
1288
1289 bool wxWindow::Close( bool force )
1290 {
1291 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1292
1293 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1294 event.SetEventObject(this);
1295 event.SetForce(force);
1296
1297 return GetEventHandler()->ProcessEvent(event);
1298 }
1299
1300 bool wxWindow::Destroy()
1301 {
1302 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1303
1304 m_hasVMT = FALSE;
1305 delete this;
1306 return TRUE;
1307 }
1308
1309 bool wxWindow::DestroyChildren()
1310 {
1311 if (GetChildren())
1312 {
1313 wxNode *node;
1314 while ((node = GetChildren()->First()) != (wxNode *)NULL)
1315 {
1316 wxWindow *child;
1317 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
1318 {
1319 delete child;
1320 if (GetChildren()->Member(child)) delete node;
1321 }
1322 }
1323 }
1324 return TRUE;
1325 }
1326
1327 void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1328 {
1329 // are we to set fonts here ?
1330 }
1331
1332 wxPoint wxWindow::GetClientAreaOrigin() const
1333 {
1334 return wxPoint(0,0);
1335 }
1336
1337 void wxWindow::AdjustForParentClientOrigin( int& x, int& y, int sizeFlags )
1338 {
1339 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
1340 {
1341 wxPoint pt(GetParent()->GetClientAreaOrigin());
1342 x += pt.x;
1343 y += pt.y;
1344 }
1345 }
1346
1347 void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
1348 {
1349 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1350 wxASSERT_MSG( (m_parent != NULL), "wxWindow::SetSize requires parent.\n" );
1351
1352 if (m_resizing) return; // I don't like recursions
1353 m_resizing = TRUE;
1354
1355 if (m_parent->m_wxwindow == NULL) // i.e. wxNotebook
1356 {
1357 // don't set the size for children of wxNotebook, just take the values.
1358 m_x = x;
1359 m_y = y;
1360 m_width = width;
1361 m_height = height;
1362 }
1363 else
1364 {
1365 int old_width = m_width;
1366 int old_height = m_height;
1367
1368 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1369 {
1370 if (x != -1) m_x = x;
1371 if (y != -1) m_y = y;
1372 if (width != -1) m_width = width;
1373 if (height != -1) m_height = height;
1374 }
1375 else
1376 {
1377 m_x = x;
1378 m_y = y;
1379 m_width = width;
1380 m_height = height;
1381 }
1382
1383 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1384 {
1385 if (width == -1) m_width = 80;
1386 }
1387
1388 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1389 {
1390 if (height == -1) m_height = 26;
1391 }
1392
1393 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1394 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
1395 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_minWidth;
1396 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_minHeight;
1397
1398 wxPoint pt( m_parent->GetClientAreaOrigin() );
1399 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x, m_y+pt.y );
1400
1401 if ((old_width != m_width) || (old_height != m_height))
1402 gtk_widget_set_usize( m_widget, m_width, m_height );
1403 }
1404
1405 m_sizeSet = TRUE;
1406
1407 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1408 event.SetEventObject( this );
1409 GetEventHandler()->ProcessEvent( event );
1410
1411 m_resizing = FALSE;
1412 }
1413
1414 void wxWindow::SetSize( int width, int height )
1415 {
1416 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
1417 }
1418
1419 void wxWindow::Move( int x, int y )
1420 {
1421 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
1422 }
1423
1424 void wxWindow::GetSize( int *width, int *height ) const
1425 {
1426 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1427
1428 if (width) (*width) = m_width;
1429 if (height) (*height) = m_height;
1430 }
1431
1432 void wxWindow::SetClientSize( int width, int height )
1433 {
1434 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1435
1436 if (!m_wxwindow)
1437 {
1438 SetSize( width, height );
1439 }
1440 else
1441 {
1442 int dw = 0;
1443 int dh = 0;
1444
1445 if (!m_hasScrolling)
1446 {
1447 GtkStyleClass *window_class = m_wxwindow->style->klass;
1448
1449 if ((m_windowStyle & wxRAISED_BORDER) ||
1450 (m_windowStyle & wxSUNKEN_BORDER))
1451 {
1452 dw += 2 * window_class->xthickness;
1453 dh += 2 * window_class->ythickness;
1454 }
1455 }
1456 else
1457 {
1458 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1459 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1460
1461 #ifdef NEW_GTK_SCROLL_CODE
1462 GtkWidget *viewport = scroll_window->child;
1463 #else
1464 GtkWidget *viewport = scroll_window->viewport;
1465 #endif
1466
1467 GtkStyleClass *viewport_class = viewport->style->klass;
1468
1469 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1470 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1471
1472 if ((m_windowStyle & wxRAISED_BORDER) ||
1473 (m_windowStyle & wxSUNKEN_BORDER))
1474 {
1475 dw += 2 * viewport_class->xthickness;
1476 dh += 2 * viewport_class->ythickness;
1477 }
1478
1479 if (scroll_window->vscrollbar_visible)
1480 {
1481 dw += vscrollbar->allocation.width;
1482 dw += scroll_class->scrollbar_spacing;
1483 }
1484
1485 if (scroll_window->hscrollbar_visible)
1486 {
1487 dh += hscrollbar->allocation.height;
1488 dw += scroll_class->scrollbar_spacing;
1489 }
1490 }
1491
1492 SetSize( width+dw, height+dh );
1493 }
1494 }
1495
1496 void wxWindow::GetClientSize( int *width, int *height ) const
1497 {
1498 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1499
1500 if (!m_wxwindow)
1501 {
1502 if (width) (*width) = m_width;
1503 if (height) (*height) = m_height;
1504 }
1505 else
1506 {
1507 int dw = 0;
1508 int dh = 0;
1509
1510 if (!m_hasScrolling)
1511 {
1512 GtkStyleClass *window_class = m_wxwindow->style->klass;
1513
1514 if ((m_windowStyle & wxRAISED_BORDER) ||
1515 (m_windowStyle & wxSUNKEN_BORDER))
1516 {
1517 dw += 2 * window_class->xthickness;
1518 dh += 2 * window_class->ythickness;
1519 }
1520 }
1521 else
1522 {
1523 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1524 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1525
1526 #ifdef NEW_GTK_SCROLL_CODE
1527 GtkWidget *viewport = scroll_window->child;
1528 #else
1529 GtkWidget *viewport = scroll_window->viewport;
1530 #endif
1531
1532 GtkStyleClass *viewport_class = viewport->style->klass;
1533
1534 if ((m_windowStyle & wxRAISED_BORDER) ||
1535 (m_windowStyle & wxSUNKEN_BORDER))
1536 {
1537 dw += 2 * viewport_class->xthickness;
1538 dh += 2 * viewport_class->ythickness;
1539 }
1540
1541 if (scroll_window->vscrollbar_visible)
1542 {
1543 // dw += vscrollbar->allocation.width;
1544 dw += 15; // range.slider_width = 11 + 2*2pts edge
1545 dw += scroll_class->scrollbar_spacing;
1546 }
1547
1548 if (scroll_window->hscrollbar_visible)
1549 {
1550 // dh += hscrollbar->allocation.height;
1551 dh += 15;
1552 dh += scroll_class->scrollbar_spacing;
1553 }
1554 }
1555
1556 if (width) (*width) = m_width - dw;
1557 if (height) (*height) = m_height - dh;
1558 }
1559 }
1560
1561 void wxWindow::GetPosition( int *x, int *y ) const
1562 {
1563 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1564
1565 if (x) (*x) = m_x;
1566 if (y) (*y) = m_y;
1567 }
1568
1569 void wxWindow::ClientToScreen( int *x, int *y )
1570 {
1571 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1572
1573 GdkWindow *source = (GdkWindow *) NULL;
1574 if (m_wxwindow)
1575 source = m_wxwindow->window;
1576 else
1577 source = m_widget->window;
1578
1579 int org_x = 0;
1580 int org_y = 0;
1581 gdk_window_get_origin( source, &org_x, &org_y );
1582
1583 if (!m_wxwindow)
1584 {
1585 if (GTK_WIDGET_NO_WINDOW (m_widget))
1586 {
1587 org_x += m_widget->allocation.x;
1588 org_y += m_widget->allocation.y;
1589 }
1590 }
1591
1592 wxPoint pt(GetClientAreaOrigin());
1593 org_x += pt.x;
1594 org_y += pt.y;
1595
1596 if (x) *x += org_x;
1597 if (y) *y += org_y;
1598 }
1599
1600 void wxWindow::ScreenToClient( int *x, int *y )
1601 {
1602 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1603
1604 GdkWindow *source = (GdkWindow *) NULL;
1605 if (m_wxwindow)
1606 source = m_wxwindow->window;
1607 else
1608 source = m_widget->window;
1609
1610 int org_x = 0;
1611 int org_y = 0;
1612 gdk_window_get_origin( source, &org_x, &org_y );
1613
1614 if (!m_wxwindow)
1615 {
1616 if (GTK_WIDGET_NO_WINDOW (m_widget))
1617 {
1618 org_x += m_widget->allocation.x;
1619 org_y += m_widget->allocation.y;
1620 }
1621 }
1622
1623 wxPoint pt(GetClientAreaOrigin());
1624 org_x -= pt.x;
1625 org_y -= pt.y;
1626
1627 if (x) *x -= org_x;
1628 if (y) *y -= org_y;
1629 }
1630
1631 void wxWindow::Centre( int direction )
1632 {
1633 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1634
1635 int x = m_x;
1636 int y = m_y;
1637
1638 if (m_parent)
1639 {
1640 int p_w = 0;
1641 int p_h = 0;
1642 m_parent->GetSize( &p_w, &p_h );
1643 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (p_w - m_width) / 2;
1644 if (direction & wxVERTICAL == wxVERTICAL) y = (p_h - m_height) / 2;
1645 }
1646 else
1647 {
1648 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
1649 if (direction & wxVERTICAL == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
1650 }
1651
1652 Move( x, y );
1653 }
1654
1655 void wxWindow::Fit()
1656 {
1657 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1658
1659 int maxX = 0;
1660 int maxY = 0;
1661 wxNode *node = GetChildren()->First();
1662 while ( node )
1663 {
1664 wxWindow *win = (wxWindow *)node->Data();
1665 int wx, wy, ww, wh;
1666 win->GetPosition(&wx, &wy);
1667 win->GetSize(&ww, &wh);
1668 if ( wx + ww > maxX )
1669 maxX = wx + ww;
1670 if ( wy + wh > maxY )
1671 maxY = wy + wh;
1672
1673 node = node->Next();
1674 }
1675 SetClientSize(maxX + 5, maxY + 10);
1676 }
1677
1678 void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
1679 {
1680 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1681
1682 m_minWidth = minW;
1683 m_minHeight = minH;
1684 m_maxWidth = maxW;
1685 m_maxHeight = maxH;
1686 }
1687
1688 void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
1689 {
1690 // if (GetAutoLayout()) Layout();
1691 }
1692
1693 bool wxWindow::Show( bool show )
1694 {
1695 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1696
1697 if (show)
1698 gtk_widget_show( m_widget );
1699 else
1700 gtk_widget_hide( m_widget );
1701 m_isShown = show;
1702 return TRUE;
1703 }
1704
1705 void wxWindow::Enable( bool enable )
1706 {
1707 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1708
1709 m_isEnabled = enable;
1710 gtk_widget_set_sensitive( m_widget, enable );
1711 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
1712 }
1713
1714 int wxWindow::GetCharHeight() const
1715 {
1716 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1717
1718 if (!m_font.Ok())
1719 {
1720 wxFAIL_MSG( "invalid font" );
1721 return -1;
1722 }
1723
1724 GdkFont *font = m_font.GetInternalFont( 1.0 );
1725 return font->ascent + font->descent;
1726 }
1727
1728 int wxWindow::GetCharWidth() const
1729 {
1730 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1731
1732 if (!m_font.Ok())
1733 {
1734 wxFAIL_MSG( "invalid font" );
1735 return -1;
1736 }
1737
1738 GdkFont *font = m_font.GetInternalFont( 1.0 );
1739 return gdk_string_width( font, "H" );
1740 }
1741
1742 void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
1743 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
1744 {
1745 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1746
1747 wxFont fontToUse = m_font;
1748 if (theFont) fontToUse = *theFont;
1749
1750 if (!fontToUse.Ok())
1751 {
1752 wxFAIL_MSG( "invalid font" );
1753 return;
1754 }
1755 wxASSERT_MSG( (m_font.Ok()), "invalid font" );
1756
1757 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
1758 if (x) (*x) = gdk_string_width( font, string );
1759 if (y) (*y) = font->ascent + font->descent;
1760 if (descent) (*descent) = font->descent;
1761 if (externalLeading) (*externalLeading) = 0; // ??
1762 }
1763
1764 void wxWindow::MakeModal( bool modal )
1765 {
1766 return;
1767 // Disable all other windows
1768 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
1769 {
1770 wxNode *node = wxTopLevelWindows.First();
1771 while (node)
1772 {
1773 wxWindow *win = (wxWindow *)node->Data();
1774 if (win != this)
1775 win->Enable(!modal);
1776
1777 node = node->Next();
1778 }
1779 }
1780 }
1781
1782 void wxWindow::SetFocus()
1783 {
1784 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1785
1786 GtkWidget *connect_widget = GetConnectWidget();
1787 if (connect_widget)
1788 {
1789 if (GTK_WIDGET_CAN_FOCUS(connect_widget) && !GTK_WIDGET_HAS_FOCUS (connect_widget) )
1790 {
1791 gtk_widget_grab_focus (connect_widget);
1792 }
1793 }
1794 }
1795
1796 bool wxWindow::OnClose()
1797 {
1798 return TRUE;
1799 }
1800
1801 void wxWindow::AddChild( wxWindow *child )
1802 {
1803 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1804 wxASSERT_MSG( (child != NULL), "invalid child" );
1805
1806 m_children.Append( child );
1807 }
1808
1809 wxList *wxWindow::GetChildren()
1810 {
1811 return (&m_children);
1812 }
1813
1814 wxWindow *wxWindow::ReParent( wxWindow *newParent )
1815 {
1816 wxWindow *oldParent = GetParent();
1817
1818 if (oldParent) oldParent->RemoveChild( this );
1819
1820 gtk_widget_unparent( m_widget );
1821
1822 if (newParent)
1823 {
1824 newParent->AddChild( this );
1825 (newParent->m_insertCallback)( newParent, this );
1826 }
1827
1828 return oldParent;
1829 }
1830
1831 void wxWindow::RemoveChild( wxWindow *child )
1832 {
1833 if (GetChildren()) GetChildren()->DeleteObject( child );
1834 child->m_parent = (wxWindow *) NULL;
1835 }
1836
1837 void wxWindow::SetReturnCode( int retCode )
1838 {
1839 m_retCode = retCode;
1840 }
1841
1842 int wxWindow::GetReturnCode()
1843 {
1844 return m_retCode;
1845 }
1846
1847 void wxWindow::Raise()
1848 {
1849 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1850
1851 if (m_widget) gdk_window_raise( m_widget->window );
1852 }
1853
1854 void wxWindow::Lower()
1855 {
1856 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1857
1858 if (m_widget) gdk_window_lower( m_widget->window );
1859 }
1860
1861 wxEvtHandler *wxWindow::GetEventHandler()
1862 {
1863 return m_eventHandler;
1864 }
1865
1866 void wxWindow::SetEventHandler( wxEvtHandler *handler )
1867 {
1868 m_eventHandler = handler;
1869 }
1870
1871 void wxWindow::PushEventHandler(wxEvtHandler *handler)
1872 {
1873 handler->SetNextHandler(GetEventHandler());
1874 SetEventHandler(handler);
1875 }
1876
1877 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
1878 {
1879 if (GetEventHandler())
1880 {
1881 wxEvtHandler *handlerA = GetEventHandler();
1882 wxEvtHandler *handlerB = handlerA->GetNextHandler();
1883 handlerA->SetNextHandler((wxEvtHandler *) NULL);
1884 SetEventHandler(handlerB);
1885 if (deleteHandler)
1886 {
1887 delete handlerA;
1888 return (wxEvtHandler*) NULL;
1889 }
1890 else
1891 return handlerA;
1892 }
1893 else
1894 return (wxEvtHandler *) NULL;
1895 }
1896
1897 wxValidator *wxWindow::GetValidator()
1898 {
1899 return m_windowValidator;
1900 }
1901
1902 void wxWindow::SetValidator( const wxValidator& validator )
1903 {
1904 if (m_windowValidator) delete m_windowValidator;
1905 m_windowValidator = validator.Clone();
1906 if (m_windowValidator) m_windowValidator->SetWindow(this);
1907 }
1908
1909 void wxWindow::SetClientObject( wxClientData *data )
1910 {
1911 if (m_clientObject) delete m_clientObject;
1912 m_clientObject = data;
1913 }
1914
1915 wxClientData *wxWindow::GetClientObject()
1916 {
1917 return m_clientObject;
1918 }
1919
1920 void wxWindow::SetClientData( void *data )
1921 {
1922 m_clientData = data;
1923 }
1924
1925 void *wxWindow::GetClientData()
1926 {
1927 return m_clientData;
1928 }
1929
1930 bool wxWindow::IsBeingDeleted()
1931 {
1932 return FALSE;
1933 }
1934
1935 void wxWindow::SetId( wxWindowID id )
1936 {
1937 m_windowId = id;
1938 }
1939
1940 wxWindowID wxWindow::GetId()
1941 {
1942 return m_windowId;
1943 }
1944
1945 void wxWindow::SetCursor( const wxCursor &cursor )
1946 {
1947 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1948
1949 if (m_cursor == NULL)
1950 {
1951 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1952 m_cursor = new wxCursor( wxCURSOR_ARROW );
1953 }
1954
1955 if (cursor.Ok())
1956 {
1957 if (*((wxCursor*)&cursor) == m_cursor) return;
1958 *m_cursor = cursor;
1959 }
1960 else
1961 {
1962 *m_cursor = *wxSTANDARD_CURSOR;
1963 }
1964
1965 if ((m_widget) && (m_widget->window))
1966 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
1967
1968 if ((m_wxwindow) && (m_wxwindow->window))
1969 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
1970 }
1971
1972 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
1973 {
1974 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1975
1976 if (eraseBackground && m_wxwindow && m_wxwindow->window)
1977 {
1978 if (rect)
1979 gdk_window_clear_area( m_wxwindow->window,
1980 rect->x,
1981 rect->y,
1982 rect->width,
1983 rect->height );
1984 else
1985 Clear();
1986 }
1987 if (!rect)
1988 {
1989 if (m_wxwindow)
1990 {
1991 int w = 0;
1992 int h = 0;
1993 GetClientSize( &w, &h );
1994
1995 GdkRectangle gdk_rect;
1996 gdk_rect.x = 0;
1997 gdk_rect.y = 0;
1998 gdk_rect.width = w;
1999 gdk_rect.height = h;
2000 gtk_widget_draw( m_wxwindow, &gdk_rect );
2001 }
2002 }
2003 else
2004 {
2005 GdkRectangle gdk_rect;
2006 gdk_rect.x = rect->x;
2007 gdk_rect.y = rect->y;
2008 gdk_rect.width = rect->width;
2009 gdk_rect.height = rect->height;
2010
2011 if (m_wxwindow)
2012 gtk_widget_draw( m_wxwindow, &gdk_rect );
2013 else
2014 gtk_widget_draw( m_widget, &gdk_rect );
2015 }
2016 }
2017
2018 wxRegion wxWindow::GetUpdateRegion() const
2019 {
2020 return m_updateRegion;
2021 }
2022
2023 bool wxWindow::IsExposed( int x, int y) const
2024 {
2025 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
2026 }
2027
2028 bool wxWindow::IsExposed( int x, int y, int w, int h ) const
2029 {
2030 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
2031 }
2032
2033 bool wxWindow::IsExposed( const wxPoint& pt ) const
2034 {
2035 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
2036 }
2037
2038 bool wxWindow::IsExposed( const wxRect& rect ) const
2039 {
2040 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
2041 }
2042
2043 void wxWindow::Clear()
2044 {
2045 wxCHECK_RET( m_widget != NULL, "invalid window" );
2046
2047 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
2048 }
2049
2050 wxColour wxWindow::GetBackgroundColour() const
2051 {
2052 return m_backgroundColour;
2053 }
2054
2055 void wxWindow::SetBackgroundColour( const wxColour &colour )
2056 {
2057 wxCHECK_RET( m_widget != NULL, "invalid window" );
2058
2059 if (m_backgroundColour == colour) return;
2060
2061 if (!m_backgroundColour.Ok())
2062 if (wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE ) == colour) return;
2063
2064 m_backgroundColour = colour;
2065 if (!m_backgroundColour.Ok()) return;
2066
2067 if (m_wxwindow)
2068 {
2069 GdkWindow *window = m_wxwindow->window;
2070 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2071 gdk_window_set_background( window, m_backgroundColour.GetColor() );
2072 gdk_window_clear( window );
2073 }
2074
2075 ApplyWidgetStyle();
2076 }
2077
2078 wxColour wxWindow::GetForegroundColour() const
2079 {
2080 return m_foregroundColour;
2081 }
2082
2083 void wxWindow::SetForegroundColour( const wxColour &colour )
2084 {
2085 wxCHECK_RET( m_widget != NULL, "invalid window" );
2086
2087 if (m_foregroundColour == colour) return;
2088
2089 m_foregroundColour = colour;
2090 if (!m_foregroundColour.Ok()) return;
2091
2092 ApplyWidgetStyle();
2093 }
2094
2095 GtkStyle *wxWindow::GetWidgetStyle()
2096 {
2097 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
2098
2099 m_widgetStyle =
2100 gtk_style_copy(
2101 gtk_widget_get_style( m_widget ) );
2102
2103 return m_widgetStyle;
2104 }
2105
2106 void wxWindow::SetWidgetStyle()
2107 {
2108 GtkStyle *style = GetWidgetStyle();
2109
2110 gdk_font_unref( style->font );
2111 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2112
2113 if (m_foregroundColour.Ok())
2114 {
2115 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2116 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2117 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2118 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2119 }
2120
2121 if (m_backgroundColour.Ok())
2122 {
2123 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2124 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2125 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2126 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2127 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2128 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2129 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2130 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2131 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2132 }
2133 }
2134
2135 void wxWindow::ApplyWidgetStyle()
2136 {
2137 }
2138
2139 bool wxWindow::Validate()
2140 {
2141 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2142
2143 wxNode *node = GetChildren()->First();
2144 while (node)
2145 {
2146 wxWindow *child = (wxWindow *)node->Data();
2147 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
2148 { return FALSE; }
2149 node = node->Next();
2150 }
2151 return TRUE;
2152 }
2153
2154 bool wxWindow::TransferDataToWindow()
2155 {
2156 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2157
2158 wxNode *node = GetChildren()->First();
2159 while (node)
2160 {
2161 wxWindow *child = (wxWindow *)node->Data();
2162 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2163 !child->GetValidator()->TransferToWindow() )
2164 {
2165 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2166 return FALSE;
2167 }
2168 node = node->Next();
2169 }
2170 return TRUE;
2171 }
2172
2173 bool wxWindow::TransferDataFromWindow()
2174 {
2175 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2176
2177 wxNode *node = GetChildren()->First();
2178 while (node)
2179 {
2180 wxWindow *child = (wxWindow *)node->Data();
2181 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
2182 { return FALSE; }
2183 node = node->Next();
2184 }
2185 return TRUE;
2186 }
2187
2188 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2189 {
2190 m_acceleratorTable = accel;
2191 }
2192
2193 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2194 {
2195 TransferDataToWindow();
2196 }
2197
2198 void wxWindow::InitDialog()
2199 {
2200 wxCHECK_RET( m_widget != NULL, "invalid window" );
2201
2202 wxInitDialogEvent event(GetId());
2203 event.SetEventObject( this );
2204 GetEventHandler()->ProcessEvent(event);
2205 }
2206
2207 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2208 {
2209 menu->SetInvokingWindow( win );
2210 wxNode *node = menu->m_items.First();
2211 while (node)
2212 {
2213 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2214 if (menuitem->IsSubMenu())
2215 SetInvokingWindow( menuitem->GetSubMenu(), win );
2216 node = node->Next();
2217 }
2218 }
2219
2220 bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
2221 {
2222 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2223
2224 wxCHECK_MSG( menu != NULL, FALSE, "invalid popup-menu" );
2225
2226 SetInvokingWindow( menu, this );
2227 gtk_menu_popup(
2228 GTK_MENU(menu->m_menu),
2229 (GtkWidget *)NULL, // parent menu shell
2230 (GtkWidget *)NULL, // parent menu item
2231 (GtkMenuPositionFunc)NULL,
2232 NULL, // client data
2233 0, // button used to activate it
2234 0//gs_timeLastClick // the time of activation
2235 );
2236 return TRUE;
2237 }
2238
2239 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2240 {
2241 wxCHECK_RET( m_widget != NULL, "invalid window" );
2242
2243 GtkWidget *dnd_widget = GetConnectWidget();
2244
2245 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
2246
2247 if (m_dropTarget) delete m_dropTarget;
2248 m_dropTarget = dropTarget;
2249
2250 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
2251 }
2252
2253 wxDropTarget *wxWindow::GetDropTarget() const
2254 {
2255 return m_dropTarget;
2256 }
2257
2258 GtkWidget* wxWindow::GetConnectWidget()
2259 {
2260 GtkWidget *connect_widget = m_widget;
2261 if (m_wxwindow) connect_widget = m_wxwindow;
2262
2263 return connect_widget;
2264 }
2265
2266 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2267 {
2268 if (m_wxwindow) return (window == m_wxwindow->window);
2269 return (window == m_widget->window);
2270 }
2271
2272 void wxWindow::SetFont( const wxFont &font )
2273 {
2274 wxCHECK_RET( m_widget != NULL, "invalid window" );
2275
2276 if (((wxFont*)&font)->Ok())
2277 m_font = font;
2278 else
2279 m_font = *wxSWISS_FONT;
2280
2281 ApplyWidgetStyle();
2282 }
2283
2284 wxFont *wxWindow::GetFont()
2285 {
2286 return &m_font;
2287 }
2288
2289 void wxWindow::SetWindowStyleFlag( long flag )
2290 {
2291 m_windowStyle = flag;
2292 }
2293
2294 long wxWindow::GetWindowStyleFlag() const
2295 {
2296 return m_windowStyle;
2297 }
2298
2299 void wxWindow::CaptureMouse()
2300 {
2301 wxCHECK_RET( m_widget != NULL, "invalid window" );
2302
2303 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
2304
2305 GtkWidget *connect_widget = GetConnectWidget();
2306 gtk_grab_add( connect_widget );
2307 gdk_pointer_grab ( connect_widget->window, FALSE,
2308 (GdkEventMask)
2309 (GDK_BUTTON_PRESS_MASK |
2310 GDK_BUTTON_RELEASE_MASK |
2311 GDK_POINTER_MOTION_MASK),
2312 (GdkWindow *) NULL, (GdkCursor *) NULL, GDK_CURRENT_TIME );
2313 g_capturing = TRUE;
2314 }
2315
2316 void wxWindow::ReleaseMouse()
2317 {
2318 wxCHECK_RET( m_widget != NULL, "invalid window" );
2319
2320 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
2321
2322 GtkWidget *connect_widget = GetConnectWidget();
2323 gtk_grab_remove( connect_widget );
2324 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2325 g_capturing = FALSE;
2326 }
2327
2328 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2329 {
2330 }
2331
2332 wxString wxWindow::GetTitle() const
2333 {
2334 return (wxString&)m_windowName;
2335 }
2336
2337 wxString wxWindow::GetLabel() const
2338 {
2339 return GetTitle();
2340 }
2341
2342 void wxWindow::SetName( const wxString &name )
2343 {
2344 m_windowName = name;
2345 }
2346
2347 wxString wxWindow::GetName() const
2348 {
2349 return (wxString&)m_windowName;
2350 }
2351
2352 bool wxWindow::IsShown() const
2353 {
2354 return m_isShown;
2355 }
2356
2357 bool wxWindow::IsRetained()
2358 {
2359 return FALSE;
2360 }
2361
2362 wxWindow *wxWindow::FindWindow( long id )
2363 {
2364 if (id == m_windowId) return this;
2365 wxNode *node = m_children.First();
2366 while (node)
2367 {
2368 wxWindow *child = (wxWindow*)node->Data();
2369 wxWindow *res = child->FindWindow( id );
2370 if (res) return res;
2371 node = node->Next();
2372 }
2373 return (wxWindow *) NULL;
2374 }
2375
2376 wxWindow *wxWindow::FindWindow( const wxString& name )
2377 {
2378 if (name == m_windowName) return this;
2379 wxNode *node = m_children.First();
2380 while (node)
2381 {
2382 wxWindow *child = (wxWindow*)node->Data();
2383 wxWindow *res = child->FindWindow( name );
2384 if (res) return res;
2385 node = node->Next();
2386 }
2387 return (wxWindow *) NULL;
2388 }
2389
2390 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
2391 int range, bool refresh )
2392 {
2393 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2394
2395 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2396
2397 if (!m_wxwindow) return;
2398
2399 m_hasScrolling = TRUE;
2400
2401 if (orient == wxHORIZONTAL)
2402 {
2403 float fpos = (float)pos;
2404 float frange = (float)range;
2405 float fthumb = (float)thumbVisible;
2406
2407 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2408 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2409 {
2410 SetScrollPos( orient, pos, refresh );
2411 return;
2412 }
2413
2414 m_oldHorizontalPos = fpos;
2415
2416 m_hAdjust->lower = 0.0;
2417 m_hAdjust->upper = frange;
2418 m_hAdjust->value = fpos;
2419 m_hAdjust->step_increment = 1.0;
2420 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2421 m_hAdjust->page_size = fthumb;
2422 }
2423 else
2424 {
2425 float fpos = (float)pos;
2426 float frange = (float)range;
2427 float fthumb = (float)thumbVisible;
2428
2429 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2430 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2431 {
2432 SetScrollPos( orient, pos, refresh );
2433 return;
2434 }
2435
2436 m_oldVerticalPos = fpos;
2437
2438 m_vAdjust->lower = 0.0;
2439 m_vAdjust->upper = frange;
2440 m_vAdjust->value = fpos;
2441 m_vAdjust->step_increment = 1.0;
2442 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2443 m_vAdjust->page_size = fthumb;
2444 }
2445
2446 if (m_wxwindow->window)
2447 {
2448 if (orient == wxHORIZONTAL)
2449 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2450 else
2451 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2452
2453 gtk_widget_set_usize( m_widget, m_width, m_height );
2454 }
2455 }
2456
2457 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
2458 {
2459 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2460
2461 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2462
2463 if (!m_wxwindow) return;
2464
2465 if (orient == wxHORIZONTAL)
2466 {
2467 float fpos = (float)pos;
2468 m_oldHorizontalPos = fpos;
2469
2470 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2471 m_hAdjust->value = fpos;
2472 }
2473 else
2474 {
2475 float fpos = (float)pos;
2476 m_oldVerticalPos = fpos;
2477 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2478 m_vAdjust->value = fpos;
2479 }
2480
2481 if (!m_isScrolling)
2482 {
2483 if (m_wxwindow->window)
2484 {
2485 if (orient == wxHORIZONTAL)
2486 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2487 else
2488 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2489 }
2490 }
2491 }
2492
2493 int wxWindow::GetScrollThumb( int orient ) const
2494 {
2495 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2496
2497 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2498
2499 if (!m_wxwindow) return 0;
2500
2501 if (orient == wxHORIZONTAL)
2502 return (int)(m_hAdjust->page_size+0.5);
2503 else
2504 return (int)(m_vAdjust->page_size+0.5);
2505 }
2506
2507 int wxWindow::GetScrollPos( int orient ) const
2508 {
2509 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2510
2511 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2512
2513 if (!m_wxwindow) return 0;
2514
2515 if (orient == wxHORIZONTAL)
2516 return (int)(m_hAdjust->value+0.5);
2517 else
2518 return (int)(m_vAdjust->value+0.5);
2519 }
2520
2521 int wxWindow::GetScrollRange( int orient ) const
2522 {
2523 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2524
2525 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2526
2527 if (!m_wxwindow) return 0;
2528
2529 if (orient == wxHORIZONTAL)
2530 return (int)(m_hAdjust->upper+0.5);
2531 else
2532 return (int)(m_vAdjust->upper+0.5);
2533 }
2534
2535 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
2536 {
2537 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2538
2539 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2540
2541 if (!m_wxwindow) return;
2542
2543 int cw = 0;
2544 int ch = 0;
2545 GetClientSize( &cw, &ch );
2546
2547 int w = cw - abs(dx);
2548 int h = ch - abs(dy);
2549 if ((h < 0) || (w < 0))
2550 {
2551 Refresh();
2552 return;
2553 }
2554 int s_x = 0;
2555 int s_y = 0;
2556 if (dx < 0) s_x = -dx;
2557 if (dy < 0) s_y = -dy;
2558 int d_x = 0;
2559 int d_y = 0;
2560 if (dx > 0) d_x = dx;
2561 if (dy > 0) d_y = dy;
2562
2563 if (!m_scrollGC)
2564 {
2565 m_scrollGC = gdk_gc_new( m_wxwindow->window );
2566 gdk_gc_set_exposures( m_scrollGC, TRUE );
2567 }
2568
2569 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
2570 m_wxwindow->window, s_x, s_y, w, h );
2571
2572 wxRect rect;
2573 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2574 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2575 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2576 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
2577
2578 Refresh( TRUE, &rect );
2579 }
2580
2581 //-------------------------------------------------------------------------------------
2582 // Layout
2583 //-------------------------------------------------------------------------------------
2584
2585 wxLayoutConstraints *wxWindow::GetConstraints() const
2586 {
2587 return m_constraints;
2588 }
2589
2590 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
2591 {
2592 if (m_constraints)
2593 {
2594 UnsetConstraints(m_constraints);
2595 delete m_constraints;
2596 }
2597 m_constraints = constraints;
2598 if (m_constraints)
2599 {
2600 // Make sure other windows know they're part of a 'meaningful relationship'
2601 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
2602 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2603 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
2604 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2605 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
2606 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2607 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
2608 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2609 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
2610 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2611 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
2612 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2613 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
2614 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2615 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
2616 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2617 }
2618 ;
2619 }
2620 ;
2621
2622 void wxWindow::SetAutoLayout( bool autoLayout )
2623 {
2624 m_autoLayout = autoLayout;
2625 }
2626
2627 bool wxWindow::GetAutoLayout() const
2628 {
2629 return m_autoLayout;
2630 }
2631
2632 wxSizer *wxWindow::GetSizer() const
2633 {
2634 return m_windowSizer;
2635 }
2636
2637 void wxWindow::SetSizerParent( wxWindow *win )
2638 {
2639 m_sizerParent = win;
2640 }
2641
2642 wxWindow *wxWindow::GetSizerParent() const
2643 {
2644 return m_sizerParent;
2645 }
2646
2647 // This removes any dangling pointers to this window
2648 // in other windows' constraintsInvolvedIn lists.
2649 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
2650 {
2651 if (c)
2652 {
2653 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2654 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2655 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2656 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2657 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
2658 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2659 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
2660 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2661 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
2662 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2663 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
2664 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2665 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
2666 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2667 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
2668 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2669 }
2670 }
2671
2672 // Back-pointer to other windows we're involved with, so if we delete
2673 // this window, we must delete any constraints we're involved with.
2674 void wxWindow::AddConstraintReference(wxWindow *otherWin)
2675 {
2676 if (!m_constraintsInvolvedIn)
2677 m_constraintsInvolvedIn = new wxList;
2678 if (!m_constraintsInvolvedIn->Member(otherWin))
2679 m_constraintsInvolvedIn->Append(otherWin);
2680 }
2681
2682 // REMOVE back-pointer to other windows we're involved with.
2683 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
2684 {
2685 if (m_constraintsInvolvedIn)
2686 m_constraintsInvolvedIn->DeleteObject(otherWin);
2687 }
2688
2689 // Reset any constraints that mention this window
2690 void wxWindow::DeleteRelatedConstraints()
2691 {
2692 if (m_constraintsInvolvedIn)
2693 {
2694 wxNode *node = m_constraintsInvolvedIn->First();
2695 while (node)
2696 {
2697 wxWindow *win = (wxWindow *)node->Data();
2698 wxNode *next = node->Next();
2699 wxLayoutConstraints *constr = win->GetConstraints();
2700
2701 // Reset any constraints involving this window
2702 if (constr)
2703 {
2704 constr->left.ResetIfWin((wxWindow *)this);
2705 constr->top.ResetIfWin((wxWindow *)this);
2706 constr->right.ResetIfWin((wxWindow *)this);
2707 constr->bottom.ResetIfWin((wxWindow *)this);
2708 constr->width.ResetIfWin((wxWindow *)this);
2709 constr->height.ResetIfWin((wxWindow *)this);
2710 constr->centreX.ResetIfWin((wxWindow *)this);
2711 constr->centreY.ResetIfWin((wxWindow *)this);
2712 }
2713 delete node;
2714 node = next;
2715 }
2716 delete m_constraintsInvolvedIn;
2717 m_constraintsInvolvedIn = (wxList *) NULL;
2718 }
2719 }
2720
2721 void wxWindow::SetSizer(wxSizer *sizer)
2722 {
2723 m_windowSizer = sizer;
2724 if (sizer)
2725 sizer->SetSizerParent((wxWindow *)this);
2726 }
2727
2728 /*
2729 * New version
2730 */
2731
2732 bool wxWindow::Layout()
2733 {
2734 if (GetConstraints())
2735 {
2736 int w, h;
2737 GetClientSize(&w, &h);
2738 GetConstraints()->width.SetValue(w);
2739 GetConstraints()->height.SetValue(h);
2740 }
2741
2742 // If top level (one sizer), evaluate the sizer's constraints.
2743 if (GetSizer())
2744 {
2745 int noChanges;
2746 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2747 GetSizer()->LayoutPhase1(&noChanges);
2748 GetSizer()->LayoutPhase2(&noChanges);
2749 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2750 return TRUE;
2751 }
2752 else
2753 {
2754 // Otherwise, evaluate child constraints
2755 ResetConstraints(); // Mark all constraints as unevaluated
2756 DoPhase(1); // Just one phase need if no sizers involved
2757 DoPhase(2);
2758 SetConstraintSizes(); // Recursively set the real window sizes
2759 }
2760 return TRUE;
2761 }
2762
2763
2764 // Do a phase of evaluating constraints:
2765 // the default behaviour. wxSizers may do a similar
2766 // thing, but also impose their own 'constraints'
2767 // and order the evaluation differently.
2768 bool wxWindow::LayoutPhase1(int *noChanges)
2769 {
2770 wxLayoutConstraints *constr = GetConstraints();
2771 if (constr)
2772 {
2773 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
2774 }
2775 else
2776 return TRUE;
2777 }
2778
2779 bool wxWindow::LayoutPhase2(int *noChanges)
2780 {
2781 *noChanges = 0;
2782
2783 // Layout children
2784 DoPhase(1);
2785 DoPhase(2);
2786 return TRUE;
2787 }
2788
2789 // Do a phase of evaluating child constraints
2790 bool wxWindow::DoPhase(int phase)
2791 {
2792 int noIterations = 0;
2793 int maxIterations = 500;
2794 int noChanges = 1;
2795 int noFailures = 0;
2796 wxList succeeded;
2797 while ((noChanges > 0) && (noIterations < maxIterations))
2798 {
2799 noChanges = 0;
2800 noFailures = 0;
2801 wxNode *node = GetChildren()->First();
2802 while (node)
2803 {
2804 wxWindow *child = (wxWindow *)node->Data();
2805 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
2806 {
2807 wxLayoutConstraints *constr = child->GetConstraints();
2808 if (constr)
2809 {
2810 if (succeeded.Member(child))
2811 {
2812 }
2813 else
2814 {
2815 int tempNoChanges = 0;
2816 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
2817 noChanges += tempNoChanges;
2818 if (success)
2819 {
2820 succeeded.Append(child);
2821 }
2822 }
2823 }
2824 }
2825 node = node->Next();
2826 }
2827 noIterations ++;
2828 }
2829 return TRUE;
2830 }
2831
2832 void wxWindow::ResetConstraints()
2833 {
2834 wxLayoutConstraints *constr = GetConstraints();
2835 if (constr)
2836 {
2837 constr->left.SetDone(FALSE);
2838 constr->top.SetDone(FALSE);
2839 constr->right.SetDone(FALSE);
2840 constr->bottom.SetDone(FALSE);
2841 constr->width.SetDone(FALSE);
2842 constr->height.SetDone(FALSE);
2843 constr->centreX.SetDone(FALSE);
2844 constr->centreY.SetDone(FALSE);
2845 }
2846 wxNode *node = GetChildren()->First();
2847 while (node)
2848 {
2849 wxWindow *win = (wxWindow *)node->Data();
2850 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2851 win->ResetConstraints();
2852 node = node->Next();
2853 }
2854 }
2855
2856 // Need to distinguish between setting the 'fake' size for
2857 // windows and sizers, and setting the real values.
2858 void wxWindow::SetConstraintSizes(bool recurse)
2859 {
2860 wxLayoutConstraints *constr = GetConstraints();
2861 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
2862 constr->width.GetDone() && constr->height.GetDone())
2863 {
2864 int x = constr->left.GetValue();
2865 int y = constr->top.GetValue();
2866 int w = constr->width.GetValue();
2867 int h = constr->height.GetValue();
2868
2869 // If we don't want to resize this window, just move it...
2870 if ((constr->width.GetRelationship() != wxAsIs) ||
2871 (constr->height.GetRelationship() != wxAsIs))
2872 {
2873 // Calls Layout() recursively. AAAGH. How can we stop that.
2874 // Simply take Layout() out of non-top level OnSizes.
2875 SizerSetSize(x, y, w, h);
2876 }
2877 else
2878 {
2879 SizerMove(x, y);
2880 }
2881 }
2882 else if (constr)
2883 {
2884 char *windowClass = this->GetClassInfo()->GetClassName();
2885
2886 wxString winName;
2887 if (GetName() == "")
2888 winName = _("unnamed");
2889 else
2890 winName = GetName();
2891 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass, (const char *)winName);
2892 if (!constr->left.GetDone())
2893 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2894 if (!constr->right.GetDone())
2895 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2896 if (!constr->width.GetDone())
2897 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2898 if (!constr->height.GetDone())
2899 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2900 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2901 }
2902
2903 if (recurse)
2904 {
2905 wxNode *node = GetChildren()->First();
2906 while (node)
2907 {
2908 wxWindow *win = (wxWindow *)node->Data();
2909 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2910 win->SetConstraintSizes();
2911 node = node->Next();
2912 }
2913 }
2914 }
2915
2916 // This assumes that all sizers are 'on' the same
2917 // window, i.e. the parent of this window.
2918 void wxWindow::TransformSizerToActual(int *x, int *y) const
2919 {
2920 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
2921 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
2922 return;
2923
2924 int xp, yp;
2925 m_sizerParent->GetPosition(&xp, &yp);
2926 m_sizerParent->TransformSizerToActual(&xp, &yp);
2927 *x += xp;
2928 *y += yp;
2929 }
2930
2931 void wxWindow::SizerSetSize(int x, int y, int w, int h)
2932 {
2933 int xx = x;
2934 int yy = y;
2935 TransformSizerToActual(&xx, &yy);
2936 SetSize(xx, yy, w, h);
2937 }
2938
2939 void wxWindow::SizerMove(int x, int y)
2940 {
2941 int xx = x;
2942 int yy = y;
2943 TransformSizerToActual(&xx, &yy);
2944 Move(xx, yy);
2945 }
2946
2947 // Only set the size/position of the constraint (if any)
2948 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
2949 {
2950 wxLayoutConstraints *constr = GetConstraints();
2951 if (constr)
2952 {
2953 if (x != -1)
2954 {
2955 constr->left.SetValue(x);
2956 constr->left.SetDone(TRUE);
2957 }
2958 if (y != -1)
2959 {
2960 constr->top.SetValue(y);
2961 constr->top.SetDone(TRUE);
2962 }
2963 if (w != -1)
2964 {
2965 constr->width.SetValue(w);
2966 constr->width.SetDone(TRUE);
2967 }
2968 if (h != -1)
2969 {
2970 constr->height.SetValue(h);
2971 constr->height.SetDone(TRUE);
2972 }
2973 }
2974 }
2975
2976 void wxWindow::MoveConstraint(int x, int y)
2977 {
2978 wxLayoutConstraints *constr = GetConstraints();
2979 if (constr)
2980 {
2981 if (x != -1)
2982 {
2983 constr->left.SetValue(x);
2984 constr->left.SetDone(TRUE);
2985 }
2986 if (y != -1)
2987 {
2988 constr->top.SetValue(y);
2989 constr->top.SetDone(TRUE);
2990 }
2991 }
2992 }
2993
2994 void wxWindow::GetSizeConstraint(int *w, int *h) const
2995 {
2996 wxLayoutConstraints *constr = GetConstraints();
2997 if (constr)
2998 {
2999 *w = constr->width.GetValue();
3000 *h = constr->height.GetValue();
3001 }
3002 else
3003 GetSize(w, h);
3004 }
3005
3006 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
3007 {
3008 wxLayoutConstraints *constr = GetConstraints();
3009 if (constr)
3010 {
3011 *w = constr->width.GetValue();
3012 *h = constr->height.GetValue();
3013 }
3014 else
3015 GetClientSize(w, h);
3016 }
3017
3018 void wxWindow::GetPositionConstraint(int *x, int *y) const
3019 {
3020 wxLayoutConstraints *constr = GetConstraints();
3021 if (constr)
3022 {
3023 *x = constr->left.GetValue();
3024 *y = constr->top.GetValue();
3025 }
3026 else
3027 GetPosition(x, y);
3028 }
3029
3030 bool wxWindow::AcceptsFocus() const
3031 {
3032 return IsEnabled() && IsShown();
3033 }
3034
3035 void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) )
3036 {
3037 UpdateWindowUI();
3038 }