]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/window.cpp
Fixed make install bug
[wxWidgets.git] / src / gtk1 / 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 == -1 ? wxNewId() : 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 wxWindow *wxWindow::ReParent( wxWindow *newParent )
1817 {
1818 wxWindow *oldParent = GetParent();
1819
1820 if (oldParent) oldParent->RemoveChild( this );
1821
1822 gtk_widget_unparent( m_widget );
1823
1824 if (newParent)
1825 {
1826 newParent->AddChild( this );
1827 (newParent->m_insertCallback)( newParent, this );
1828 }
1829
1830 return oldParent;
1831 }
1832
1833 void wxWindow::RemoveChild( wxWindow *child )
1834 {
1835 if (GetChildren()) GetChildren()->DeleteObject( child );
1836 child->m_parent = (wxWindow *) NULL;
1837 }
1838
1839 void wxWindow::SetReturnCode( int retCode )
1840 {
1841 m_retCode = retCode;
1842 }
1843
1844 int wxWindow::GetReturnCode()
1845 {
1846 return m_retCode;
1847 }
1848
1849 void wxWindow::Raise()
1850 {
1851 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1852
1853 if (m_widget) gdk_window_raise( m_widget->window );
1854 }
1855
1856 void wxWindow::Lower()
1857 {
1858 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1859
1860 if (m_widget) gdk_window_lower( m_widget->window );
1861 }
1862
1863 wxEvtHandler *wxWindow::GetEventHandler()
1864 {
1865 return m_eventHandler;
1866 }
1867
1868 void wxWindow::SetEventHandler( wxEvtHandler *handler )
1869 {
1870 m_eventHandler = handler;
1871 }
1872
1873 void wxWindow::PushEventHandler(wxEvtHandler *handler)
1874 {
1875 handler->SetNextHandler(GetEventHandler());
1876 SetEventHandler(handler);
1877 }
1878
1879 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
1880 {
1881 if (GetEventHandler())
1882 {
1883 wxEvtHandler *handlerA = GetEventHandler();
1884 wxEvtHandler *handlerB = handlerA->GetNextHandler();
1885 handlerA->SetNextHandler((wxEvtHandler *) NULL);
1886 SetEventHandler(handlerB);
1887 if (deleteHandler)
1888 {
1889 delete handlerA;
1890 return (wxEvtHandler*) NULL;
1891 }
1892 else
1893 return handlerA;
1894 }
1895 else
1896 return (wxEvtHandler *) NULL;
1897 }
1898
1899 wxValidator *wxWindow::GetValidator()
1900 {
1901 return m_windowValidator;
1902 }
1903
1904 void wxWindow::SetValidator( const wxValidator& validator )
1905 {
1906 if (m_windowValidator) delete m_windowValidator;
1907 m_windowValidator = validator.Clone();
1908 if (m_windowValidator) m_windowValidator->SetWindow(this);
1909 }
1910
1911 void wxWindow::SetClientObject( wxClientData *data )
1912 {
1913 if (m_clientObject) delete m_clientObject;
1914 m_clientObject = data;
1915 }
1916
1917 wxClientData *wxWindow::GetClientObject()
1918 {
1919 return m_clientObject;
1920 }
1921
1922 void wxWindow::SetClientData( void *data )
1923 {
1924 m_clientData = data;
1925 }
1926
1927 void *wxWindow::GetClientData()
1928 {
1929 return m_clientData;
1930 }
1931
1932 bool wxWindow::IsBeingDeleted()
1933 {
1934 return FALSE;
1935 }
1936
1937 void wxWindow::SetId( wxWindowID id )
1938 {
1939 m_windowId = id;
1940 }
1941
1942 wxWindowID wxWindow::GetId()
1943 {
1944 return m_windowId;
1945 }
1946
1947 void wxWindow::SetCursor( const wxCursor &cursor )
1948 {
1949 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1950
1951 if (m_cursor == NULL)
1952 {
1953 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1954 m_cursor = new wxCursor( wxCURSOR_ARROW );
1955 }
1956
1957 if (cursor.Ok())
1958 {
1959 if (*((wxCursor*)&cursor) == m_cursor) return;
1960 *m_cursor = cursor;
1961 }
1962 else
1963 {
1964 *m_cursor = *wxSTANDARD_CURSOR;
1965 }
1966
1967 if ((m_widget) && (m_widget->window))
1968 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
1969
1970 if ((m_wxwindow) && (m_wxwindow->window))
1971 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
1972 }
1973
1974 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
1975 {
1976 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1977
1978 if (eraseBackground && m_wxwindow && m_wxwindow->window)
1979 {
1980 if (rect)
1981 gdk_window_clear_area( m_wxwindow->window,
1982 rect->x,
1983 rect->y,
1984 rect->width,
1985 rect->height );
1986 else
1987 Clear();
1988 }
1989 if (!rect)
1990 {
1991 if (m_wxwindow)
1992 {
1993 int w = 0;
1994 int h = 0;
1995 GetClientSize( &w, &h );
1996
1997 GdkRectangle gdk_rect;
1998 gdk_rect.x = 0;
1999 gdk_rect.y = 0;
2000 gdk_rect.width = w;
2001 gdk_rect.height = h;
2002 gtk_widget_draw( m_wxwindow, &gdk_rect );
2003 }
2004 }
2005 else
2006 {
2007 GdkRectangle gdk_rect;
2008 gdk_rect.x = rect->x;
2009 gdk_rect.y = rect->y;
2010 gdk_rect.width = rect->width;
2011 gdk_rect.height = rect->height;
2012
2013 if (m_wxwindow)
2014 gtk_widget_draw( m_wxwindow, &gdk_rect );
2015 else
2016 gtk_widget_draw( m_widget, &gdk_rect );
2017 }
2018 }
2019
2020 wxRegion wxWindow::GetUpdateRegion() const
2021 {
2022 return m_updateRegion;
2023 }
2024
2025 bool wxWindow::IsExposed( int x, int y) const
2026 {
2027 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
2028 }
2029
2030 bool wxWindow::IsExposed( int x, int y, int w, int h ) const
2031 {
2032 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
2033 }
2034
2035 bool wxWindow::IsExposed( const wxPoint& pt ) const
2036 {
2037 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
2038 }
2039
2040 bool wxWindow::IsExposed( const wxRect& rect ) const
2041 {
2042 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
2043 }
2044
2045 void wxWindow::Clear()
2046 {
2047 wxCHECK_RET( m_widget != NULL, "invalid window" );
2048
2049 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
2050 }
2051
2052 wxColour wxWindow::GetBackgroundColour() const
2053 {
2054 return m_backgroundColour;
2055 }
2056
2057 void wxWindow::SetBackgroundColour( const wxColour &colour )
2058 {
2059 wxCHECK_RET( m_widget != NULL, "invalid window" );
2060
2061 if (m_backgroundColour == colour) return;
2062
2063 if (!m_backgroundColour.Ok())
2064 if (wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE ) == colour) return;
2065
2066 m_backgroundColour = colour;
2067 if (!m_backgroundColour.Ok()) return;
2068
2069 if (m_wxwindow)
2070 {
2071 GdkWindow *window = m_wxwindow->window;
2072 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2073 gdk_window_set_background( window, m_backgroundColour.GetColor() );
2074 gdk_window_clear( window );
2075 }
2076
2077 ApplyWidgetStyle();
2078 }
2079
2080 wxColour wxWindow::GetForegroundColour() const
2081 {
2082 return m_foregroundColour;
2083 }
2084
2085 void wxWindow::SetForegroundColour( const wxColour &colour )
2086 {
2087 wxCHECK_RET( m_widget != NULL, "invalid window" );
2088
2089 if (m_foregroundColour == colour) return;
2090
2091 m_foregroundColour = colour;
2092 if (!m_foregroundColour.Ok()) return;
2093
2094 ApplyWidgetStyle();
2095 }
2096
2097 GtkStyle *wxWindow::GetWidgetStyle()
2098 {
2099 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
2100
2101 m_widgetStyle =
2102 gtk_style_copy(
2103 gtk_widget_get_style( m_widget ) );
2104
2105 return m_widgetStyle;
2106 }
2107
2108 void wxWindow::SetWidgetStyle()
2109 {
2110 GtkStyle *style = GetWidgetStyle();
2111
2112 gdk_font_unref( style->font );
2113 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2114
2115 if (m_foregroundColour.Ok())
2116 {
2117 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2118 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2119 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2120 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2121 }
2122
2123 if (m_backgroundColour.Ok())
2124 {
2125 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2126 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2127 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2128 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2129 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2130 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2131 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2132 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2133 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2134 }
2135 }
2136
2137 void wxWindow::ApplyWidgetStyle()
2138 {
2139 }
2140
2141 bool wxWindow::Validate()
2142 {
2143 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2144
2145 wxNode *node = GetChildren()->First();
2146 while (node)
2147 {
2148 wxWindow *child = (wxWindow *)node->Data();
2149 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
2150 { return FALSE; }
2151 node = node->Next();
2152 }
2153 return TRUE;
2154 }
2155
2156 bool wxWindow::TransferDataToWindow()
2157 {
2158 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2159
2160 wxNode *node = GetChildren()->First();
2161 while (node)
2162 {
2163 wxWindow *child = (wxWindow *)node->Data();
2164 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2165 !child->GetValidator()->TransferToWindow() )
2166 {
2167 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2168 return FALSE;
2169 }
2170 node = node->Next();
2171 }
2172 return TRUE;
2173 }
2174
2175 bool wxWindow::TransferDataFromWindow()
2176 {
2177 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2178
2179 wxNode *node = GetChildren()->First();
2180 while (node)
2181 {
2182 wxWindow *child = (wxWindow *)node->Data();
2183 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
2184 { return FALSE; }
2185 node = node->Next();
2186 }
2187 return TRUE;
2188 }
2189
2190 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2191 {
2192 m_acceleratorTable = accel;
2193 }
2194
2195 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2196 {
2197 TransferDataToWindow();
2198 }
2199
2200 void wxWindow::InitDialog()
2201 {
2202 wxCHECK_RET( m_widget != NULL, "invalid window" );
2203
2204 wxInitDialogEvent event(GetId());
2205 event.SetEventObject( this );
2206 GetEventHandler()->ProcessEvent(event);
2207 }
2208
2209 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2210 {
2211 menu->SetInvokingWindow( win );
2212 wxNode *node = menu->m_items.First();
2213 while (node)
2214 {
2215 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2216 if (menuitem->IsSubMenu())
2217 SetInvokingWindow( menuitem->GetSubMenu(), win );
2218 node = node->Next();
2219 }
2220 }
2221
2222 bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
2223 {
2224 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2225
2226 wxCHECK_MSG( menu != NULL, FALSE, "invalid popup-menu" );
2227
2228 SetInvokingWindow( menu, this );
2229 gtk_menu_popup(
2230 GTK_MENU(menu->m_menu),
2231 (GtkWidget *)NULL, // parent menu shell
2232 (GtkWidget *)NULL, // parent menu item
2233 (GtkMenuPositionFunc)NULL,
2234 NULL, // client data
2235 0, // button used to activate it
2236 0//gs_timeLastClick // the time of activation
2237 );
2238 return TRUE;
2239 }
2240
2241 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2242 {
2243 wxCHECK_RET( m_widget != NULL, "invalid window" );
2244
2245 GtkWidget *dnd_widget = GetConnectWidget();
2246
2247 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
2248
2249 if (m_dropTarget) delete m_dropTarget;
2250 m_dropTarget = dropTarget;
2251
2252 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
2253 }
2254
2255 wxDropTarget *wxWindow::GetDropTarget() const
2256 {
2257 return m_dropTarget;
2258 }
2259
2260 GtkWidget* wxWindow::GetConnectWidget()
2261 {
2262 GtkWidget *connect_widget = m_widget;
2263 if (m_wxwindow) connect_widget = m_wxwindow;
2264
2265 return connect_widget;
2266 }
2267
2268 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2269 {
2270 if (m_wxwindow) return (window == m_wxwindow->window);
2271 return (window == m_widget->window);
2272 }
2273
2274 void wxWindow::SetFont( const wxFont &font )
2275 {
2276 wxCHECK_RET( m_widget != NULL, "invalid window" );
2277
2278 if (((wxFont*)&font)->Ok())
2279 m_font = font;
2280 else
2281 m_font = *wxSWISS_FONT;
2282
2283 ApplyWidgetStyle();
2284 }
2285
2286 wxFont *wxWindow::GetFont()
2287 {
2288 return &m_font;
2289 }
2290
2291 void wxWindow::SetWindowStyleFlag( long flag )
2292 {
2293 m_windowStyle = flag;
2294 }
2295
2296 long wxWindow::GetWindowStyleFlag() const
2297 {
2298 return m_windowStyle;
2299 }
2300
2301 void wxWindow::CaptureMouse()
2302 {
2303 wxCHECK_RET( m_widget != NULL, "invalid window" );
2304
2305 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
2306
2307 GtkWidget *connect_widget = GetConnectWidget();
2308 gtk_grab_add( connect_widget );
2309 gdk_pointer_grab ( connect_widget->window, FALSE,
2310 (GdkEventMask)
2311 (GDK_BUTTON_PRESS_MASK |
2312 GDK_BUTTON_RELEASE_MASK |
2313 GDK_POINTER_MOTION_MASK),
2314 (GdkWindow *) NULL, (GdkCursor *) NULL, GDK_CURRENT_TIME );
2315 g_capturing = TRUE;
2316 }
2317
2318 void wxWindow::ReleaseMouse()
2319 {
2320 wxCHECK_RET( m_widget != NULL, "invalid window" );
2321
2322 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
2323
2324 GtkWidget *connect_widget = GetConnectWidget();
2325 gtk_grab_remove( connect_widget );
2326 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2327 g_capturing = FALSE;
2328 }
2329
2330 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2331 {
2332 }
2333
2334 wxString wxWindow::GetTitle() const
2335 {
2336 return (wxString&)m_windowName;
2337 }
2338
2339 wxString wxWindow::GetLabel() const
2340 {
2341 return GetTitle();
2342 }
2343
2344 void wxWindow::SetName( const wxString &name )
2345 {
2346 m_windowName = name;
2347 }
2348
2349 wxString wxWindow::GetName() const
2350 {
2351 return (wxString&)m_windowName;
2352 }
2353
2354 bool wxWindow::IsShown() const
2355 {
2356 return m_isShown;
2357 }
2358
2359 bool wxWindow::IsRetained()
2360 {
2361 return FALSE;
2362 }
2363
2364 wxWindow *wxWindow::FindWindow( long id )
2365 {
2366 if (id == m_windowId) return this;
2367 wxNode *node = m_children.First();
2368 while (node)
2369 {
2370 wxWindow *child = (wxWindow*)node->Data();
2371 wxWindow *res = child->FindWindow( id );
2372 if (res) return res;
2373 node = node->Next();
2374 }
2375 return (wxWindow *) NULL;
2376 }
2377
2378 wxWindow *wxWindow::FindWindow( const wxString& name )
2379 {
2380 if (name == m_windowName) return this;
2381 wxNode *node = m_children.First();
2382 while (node)
2383 {
2384 wxWindow *child = (wxWindow*)node->Data();
2385 wxWindow *res = child->FindWindow( name );
2386 if (res) return res;
2387 node = node->Next();
2388 }
2389 return (wxWindow *) NULL;
2390 }
2391
2392 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
2393 int range, bool refresh )
2394 {
2395 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2396
2397 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2398
2399 if (!m_wxwindow) return;
2400
2401 m_hasScrolling = TRUE;
2402
2403 if (orient == wxHORIZONTAL)
2404 {
2405 float fpos = (float)pos;
2406 float frange = (float)range;
2407 float fthumb = (float)thumbVisible;
2408
2409 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2410 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2411 {
2412 SetScrollPos( orient, pos, refresh );
2413 return;
2414 }
2415
2416 m_oldHorizontalPos = fpos;
2417
2418 m_hAdjust->lower = 0.0;
2419 m_hAdjust->upper = frange;
2420 m_hAdjust->value = fpos;
2421 m_hAdjust->step_increment = 1.0;
2422 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2423 m_hAdjust->page_size = fthumb;
2424 }
2425 else
2426 {
2427 float fpos = (float)pos;
2428 float frange = (float)range;
2429 float fthumb = (float)thumbVisible;
2430
2431 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2432 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2433 {
2434 SetScrollPos( orient, pos, refresh );
2435 return;
2436 }
2437
2438 m_oldVerticalPos = fpos;
2439
2440 m_vAdjust->lower = 0.0;
2441 m_vAdjust->upper = frange;
2442 m_vAdjust->value = fpos;
2443 m_vAdjust->step_increment = 1.0;
2444 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2445 m_vAdjust->page_size = fthumb;
2446 }
2447
2448 if (m_wxwindow->window)
2449 {
2450 if (orient == wxHORIZONTAL)
2451 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2452 else
2453 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2454
2455 gtk_widget_set_usize( m_widget, m_width, m_height );
2456 }
2457 }
2458
2459 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
2460 {
2461 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2462
2463 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2464
2465 if (!m_wxwindow) return;
2466
2467 if (orient == wxHORIZONTAL)
2468 {
2469 float fpos = (float)pos;
2470 m_oldHorizontalPos = fpos;
2471
2472 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2473 m_hAdjust->value = fpos;
2474 }
2475 else
2476 {
2477 float fpos = (float)pos;
2478 m_oldVerticalPos = fpos;
2479 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2480 m_vAdjust->value = fpos;
2481 }
2482
2483 if (!m_isScrolling)
2484 {
2485 if (m_wxwindow->window)
2486 {
2487 if (orient == wxHORIZONTAL)
2488 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2489 else
2490 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2491 }
2492 }
2493 }
2494
2495 int wxWindow::GetScrollThumb( int orient ) const
2496 {
2497 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2498
2499 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2500
2501 if (!m_wxwindow) return 0;
2502
2503 if (orient == wxHORIZONTAL)
2504 return (int)(m_hAdjust->page_size+0.5);
2505 else
2506 return (int)(m_vAdjust->page_size+0.5);
2507 }
2508
2509 int wxWindow::GetScrollPos( int orient ) const
2510 {
2511 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2512
2513 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2514
2515 if (!m_wxwindow) return 0;
2516
2517 if (orient == wxHORIZONTAL)
2518 return (int)(m_hAdjust->value+0.5);
2519 else
2520 return (int)(m_vAdjust->value+0.5);
2521 }
2522
2523 int wxWindow::GetScrollRange( int orient ) const
2524 {
2525 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2526
2527 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2528
2529 if (!m_wxwindow) return 0;
2530
2531 if (orient == wxHORIZONTAL)
2532 return (int)(m_hAdjust->upper+0.5);
2533 else
2534 return (int)(m_vAdjust->upper+0.5);
2535 }
2536
2537 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
2538 {
2539 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2540
2541 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2542
2543 if (!m_wxwindow) return;
2544
2545 int cw = 0;
2546 int ch = 0;
2547 GetClientSize( &cw, &ch );
2548
2549 int w = cw - abs(dx);
2550 int h = ch - abs(dy);
2551 if ((h < 0) || (w < 0))
2552 {
2553 Refresh();
2554 return;
2555 }
2556 int s_x = 0;
2557 int s_y = 0;
2558 if (dx < 0) s_x = -dx;
2559 if (dy < 0) s_y = -dy;
2560 int d_x = 0;
2561 int d_y = 0;
2562 if (dx > 0) d_x = dx;
2563 if (dy > 0) d_y = dy;
2564
2565 if (!m_scrollGC)
2566 {
2567 m_scrollGC = gdk_gc_new( m_wxwindow->window );
2568 gdk_gc_set_exposures( m_scrollGC, TRUE );
2569 }
2570
2571 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
2572 m_wxwindow->window, s_x, s_y, w, h );
2573
2574 wxRect rect;
2575 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2576 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2577 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2578 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
2579
2580 Refresh( TRUE, &rect );
2581 }
2582
2583 //-------------------------------------------------------------------------------------
2584 // Layout
2585 //-------------------------------------------------------------------------------------
2586
2587 wxLayoutConstraints *wxWindow::GetConstraints() const
2588 {
2589 return m_constraints;
2590 }
2591
2592 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
2593 {
2594 if (m_constraints)
2595 {
2596 UnsetConstraints(m_constraints);
2597 delete m_constraints;
2598 }
2599 m_constraints = constraints;
2600 if (m_constraints)
2601 {
2602 // Make sure other windows know they're part of a 'meaningful relationship'
2603 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
2604 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2605 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
2606 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2607 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
2608 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2609 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
2610 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2611 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
2612 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2613 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
2614 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2615 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
2616 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2617 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
2618 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2619 }
2620 ;
2621 }
2622 ;
2623
2624 void wxWindow::SetAutoLayout( bool autoLayout )
2625 {
2626 m_autoLayout = autoLayout;
2627 }
2628
2629 bool wxWindow::GetAutoLayout() const
2630 {
2631 return m_autoLayout;
2632 }
2633
2634 wxSizer *wxWindow::GetSizer() const
2635 {
2636 return m_windowSizer;
2637 }
2638
2639 void wxWindow::SetSizerParent( wxWindow *win )
2640 {
2641 m_sizerParent = win;
2642 }
2643
2644 wxWindow *wxWindow::GetSizerParent() const
2645 {
2646 return m_sizerParent;
2647 }
2648
2649 // This removes any dangling pointers to this window
2650 // in other windows' constraintsInvolvedIn lists.
2651 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
2652 {
2653 if (c)
2654 {
2655 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2656 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2657 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2658 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2659 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
2660 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2661 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
2662 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2663 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
2664 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2665 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
2666 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2667 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
2668 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2669 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
2670 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2671 }
2672 }
2673
2674 // Back-pointer to other windows we're involved with, so if we delete
2675 // this window, we must delete any constraints we're involved with.
2676 void wxWindow::AddConstraintReference(wxWindow *otherWin)
2677 {
2678 if (!m_constraintsInvolvedIn)
2679 m_constraintsInvolvedIn = new wxList;
2680 if (!m_constraintsInvolvedIn->Member(otherWin))
2681 m_constraintsInvolvedIn->Append(otherWin);
2682 }
2683
2684 // REMOVE back-pointer to other windows we're involved with.
2685 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
2686 {
2687 if (m_constraintsInvolvedIn)
2688 m_constraintsInvolvedIn->DeleteObject(otherWin);
2689 }
2690
2691 // Reset any constraints that mention this window
2692 void wxWindow::DeleteRelatedConstraints()
2693 {
2694 if (m_constraintsInvolvedIn)
2695 {
2696 wxNode *node = m_constraintsInvolvedIn->First();
2697 while (node)
2698 {
2699 wxWindow *win = (wxWindow *)node->Data();
2700 wxNode *next = node->Next();
2701 wxLayoutConstraints *constr = win->GetConstraints();
2702
2703 // Reset any constraints involving this window
2704 if (constr)
2705 {
2706 constr->left.ResetIfWin((wxWindow *)this);
2707 constr->top.ResetIfWin((wxWindow *)this);
2708 constr->right.ResetIfWin((wxWindow *)this);
2709 constr->bottom.ResetIfWin((wxWindow *)this);
2710 constr->width.ResetIfWin((wxWindow *)this);
2711 constr->height.ResetIfWin((wxWindow *)this);
2712 constr->centreX.ResetIfWin((wxWindow *)this);
2713 constr->centreY.ResetIfWin((wxWindow *)this);
2714 }
2715 delete node;
2716 node = next;
2717 }
2718 delete m_constraintsInvolvedIn;
2719 m_constraintsInvolvedIn = (wxList *) NULL;
2720 }
2721 }
2722
2723 void wxWindow::SetSizer(wxSizer *sizer)
2724 {
2725 m_windowSizer = sizer;
2726 if (sizer)
2727 sizer->SetSizerParent((wxWindow *)this);
2728 }
2729
2730 /*
2731 * New version
2732 */
2733
2734 bool wxWindow::Layout()
2735 {
2736 if (GetConstraints())
2737 {
2738 int w, h;
2739 GetClientSize(&w, &h);
2740 GetConstraints()->width.SetValue(w);
2741 GetConstraints()->height.SetValue(h);
2742 }
2743
2744 // If top level (one sizer), evaluate the sizer's constraints.
2745 if (GetSizer())
2746 {
2747 int noChanges;
2748 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2749 GetSizer()->LayoutPhase1(&noChanges);
2750 GetSizer()->LayoutPhase2(&noChanges);
2751 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2752 return TRUE;
2753 }
2754 else
2755 {
2756 // Otherwise, evaluate child constraints
2757 ResetConstraints(); // Mark all constraints as unevaluated
2758 DoPhase(1); // Just one phase need if no sizers involved
2759 DoPhase(2);
2760 SetConstraintSizes(); // Recursively set the real window sizes
2761 }
2762 return TRUE;
2763 }
2764
2765
2766 // Do a phase of evaluating constraints:
2767 // the default behaviour. wxSizers may do a similar
2768 // thing, but also impose their own 'constraints'
2769 // and order the evaluation differently.
2770 bool wxWindow::LayoutPhase1(int *noChanges)
2771 {
2772 wxLayoutConstraints *constr = GetConstraints();
2773 if (constr)
2774 {
2775 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
2776 }
2777 else
2778 return TRUE;
2779 }
2780
2781 bool wxWindow::LayoutPhase2(int *noChanges)
2782 {
2783 *noChanges = 0;
2784
2785 // Layout children
2786 DoPhase(1);
2787 DoPhase(2);
2788 return TRUE;
2789 }
2790
2791 // Do a phase of evaluating child constraints
2792 bool wxWindow::DoPhase(int phase)
2793 {
2794 int noIterations = 0;
2795 int maxIterations = 500;
2796 int noChanges = 1;
2797 int noFailures = 0;
2798 wxList succeeded;
2799 while ((noChanges > 0) && (noIterations < maxIterations))
2800 {
2801 noChanges = 0;
2802 noFailures = 0;
2803 wxNode *node = GetChildren()->First();
2804 while (node)
2805 {
2806 wxWindow *child = (wxWindow *)node->Data();
2807 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
2808 {
2809 wxLayoutConstraints *constr = child->GetConstraints();
2810 if (constr)
2811 {
2812 if (succeeded.Member(child))
2813 {
2814 }
2815 else
2816 {
2817 int tempNoChanges = 0;
2818 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
2819 noChanges += tempNoChanges;
2820 if (success)
2821 {
2822 succeeded.Append(child);
2823 }
2824 }
2825 }
2826 }
2827 node = node->Next();
2828 }
2829 noIterations ++;
2830 }
2831 return TRUE;
2832 }
2833
2834 void wxWindow::ResetConstraints()
2835 {
2836 wxLayoutConstraints *constr = GetConstraints();
2837 if (constr)
2838 {
2839 constr->left.SetDone(FALSE);
2840 constr->top.SetDone(FALSE);
2841 constr->right.SetDone(FALSE);
2842 constr->bottom.SetDone(FALSE);
2843 constr->width.SetDone(FALSE);
2844 constr->height.SetDone(FALSE);
2845 constr->centreX.SetDone(FALSE);
2846 constr->centreY.SetDone(FALSE);
2847 }
2848 wxNode *node = GetChildren()->First();
2849 while (node)
2850 {
2851 wxWindow *win = (wxWindow *)node->Data();
2852 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2853 win->ResetConstraints();
2854 node = node->Next();
2855 }
2856 }
2857
2858 // Need to distinguish between setting the 'fake' size for
2859 // windows and sizers, and setting the real values.
2860 void wxWindow::SetConstraintSizes(bool recurse)
2861 {
2862 wxLayoutConstraints *constr = GetConstraints();
2863 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
2864 constr->width.GetDone() && constr->height.GetDone())
2865 {
2866 int x = constr->left.GetValue();
2867 int y = constr->top.GetValue();
2868 int w = constr->width.GetValue();
2869 int h = constr->height.GetValue();
2870
2871 // If we don't want to resize this window, just move it...
2872 if ((constr->width.GetRelationship() != wxAsIs) ||
2873 (constr->height.GetRelationship() != wxAsIs))
2874 {
2875 // Calls Layout() recursively. AAAGH. How can we stop that.
2876 // Simply take Layout() out of non-top level OnSizes.
2877 SizerSetSize(x, y, w, h);
2878 }
2879 else
2880 {
2881 SizerMove(x, y);
2882 }
2883 }
2884 else if (constr)
2885 {
2886 char *windowClass = this->GetClassInfo()->GetClassName();
2887
2888 wxString winName;
2889 if (GetName() == "")
2890 winName = _("unnamed");
2891 else
2892 winName = GetName();
2893 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass, (const char *)winName);
2894 if (!constr->left.GetDone())
2895 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2896 if (!constr->right.GetDone())
2897 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2898 if (!constr->width.GetDone())
2899 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2900 if (!constr->height.GetDone())
2901 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2902 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2903 }
2904
2905 if (recurse)
2906 {
2907 wxNode *node = GetChildren()->First();
2908 while (node)
2909 {
2910 wxWindow *win = (wxWindow *)node->Data();
2911 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2912 win->SetConstraintSizes();
2913 node = node->Next();
2914 }
2915 }
2916 }
2917
2918 // This assumes that all sizers are 'on' the same
2919 // window, i.e. the parent of this window.
2920 void wxWindow::TransformSizerToActual(int *x, int *y) const
2921 {
2922 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
2923 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
2924 return;
2925
2926 int xp, yp;
2927 m_sizerParent->GetPosition(&xp, &yp);
2928 m_sizerParent->TransformSizerToActual(&xp, &yp);
2929 *x += xp;
2930 *y += yp;
2931 }
2932
2933 void wxWindow::SizerSetSize(int x, int y, int w, int h)
2934 {
2935 int xx = x;
2936 int yy = y;
2937 TransformSizerToActual(&xx, &yy);
2938 SetSize(xx, yy, w, h);
2939 }
2940
2941 void wxWindow::SizerMove(int x, int y)
2942 {
2943 int xx = x;
2944 int yy = y;
2945 TransformSizerToActual(&xx, &yy);
2946 Move(xx, yy);
2947 }
2948
2949 // Only set the size/position of the constraint (if any)
2950 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
2951 {
2952 wxLayoutConstraints *constr = GetConstraints();
2953 if (constr)
2954 {
2955 if (x != -1)
2956 {
2957 constr->left.SetValue(x);
2958 constr->left.SetDone(TRUE);
2959 }
2960 if (y != -1)
2961 {
2962 constr->top.SetValue(y);
2963 constr->top.SetDone(TRUE);
2964 }
2965 if (w != -1)
2966 {
2967 constr->width.SetValue(w);
2968 constr->width.SetDone(TRUE);
2969 }
2970 if (h != -1)
2971 {
2972 constr->height.SetValue(h);
2973 constr->height.SetDone(TRUE);
2974 }
2975 }
2976 }
2977
2978 void wxWindow::MoveConstraint(int x, int y)
2979 {
2980 wxLayoutConstraints *constr = GetConstraints();
2981 if (constr)
2982 {
2983 if (x != -1)
2984 {
2985 constr->left.SetValue(x);
2986 constr->left.SetDone(TRUE);
2987 }
2988 if (y != -1)
2989 {
2990 constr->top.SetValue(y);
2991 constr->top.SetDone(TRUE);
2992 }
2993 }
2994 }
2995
2996 void wxWindow::GetSizeConstraint(int *w, int *h) const
2997 {
2998 wxLayoutConstraints *constr = GetConstraints();
2999 if (constr)
3000 {
3001 *w = constr->width.GetValue();
3002 *h = constr->height.GetValue();
3003 }
3004 else
3005 GetSize(w, h);
3006 }
3007
3008 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
3009 {
3010 wxLayoutConstraints *constr = GetConstraints();
3011 if (constr)
3012 {
3013 *w = constr->width.GetValue();
3014 *h = constr->height.GetValue();
3015 }
3016 else
3017 GetClientSize(w, h);
3018 }
3019
3020 void wxWindow::GetPositionConstraint(int *x, int *y) const
3021 {
3022 wxLayoutConstraints *constr = GetConstraints();
3023 if (constr)
3024 {
3025 *x = constr->left.GetValue();
3026 *y = constr->top.GetValue();
3027 }
3028 else
3029 GetPosition(x, y);
3030 }
3031
3032 bool wxWindow::AcceptsFocus() const
3033 {
3034 return IsEnabled() && IsShown();
3035 }
3036
3037 void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) )
3038 {
3039 UpdateWindowUI();
3040 }