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