]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/window.cpp
6da95fff04c8967a783dd110217cd7eb36a95a44
[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 "gdk/gdkprivate.h"
30 #include "gdk/gdkkeysyms.h"
31
32 #include <math.h>
33
34 //-----------------------------------------------------------------------------
35 // documentation on internals
36 //-----------------------------------------------------------------------------
37
38 /*
39 I have been asked several times about writing some documentation about
40 the GTK port of wxWindows, especially its internal structures. Obviously,
41 you cannot understand wxGTK without knowing a little about the GTK, but
42 some more information about what the wxWindow, which is the base class
43 for all other window classes, does seems required as well.
44
45 What does wxWindow do? It contains the common interface for the following
46 jobs of its descendants:
47
48 1) Define the rudimentary behaviour common to all window classes, such as
49 resizing, intercepting user input (so as to make it possible to use these
50 events for special purposes in a derived class), window names etc.
51
52 2) Provide the possibility to contain and manage children, if the derived
53 class is allowed to contain children, which holds true for those window
54 classes which do not display a native GTK widget. To name them, these
55 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
56 work classes are a special case and are handled a bit differently from
57 the rest. The same holds true for the wxNotebook class.
58
59 3) Provide the possibility to draw into a client area of a window. This,
60 too, only holds true for classes that do not display a native GTK widget
61 as above.
62
63 4) Provide the entire mechanism for scrolling widgets. This actual inter-
64 face for this is usually in wxScrolledWindow, but the GTK implementation
65 is in this class.
66
67 5) A multitude of helper or extra methods for special purposes, such as
68 Drag'n'Drop, managing validators etc.
69
70 Normally one might expect, that one wxWindows window would always correspond
71 to one GTK widget. Under GTK, there is no such allround widget that has all
72 the functionality. Moreover, the GTK defines a client area as a different
73 widget from the actual widget you are handling. Last but not least some
74 special classes (e.g. wxFrame) handle different categories of widgets and
75 still have the possibility to draw something in the client area.
76 It was therefore required to write a special purpose GTK widget, that would
77 represent a client area in the sense of wxWindows capable to do the jobs
78 2), 3) and 4). I have written this class and it resides in win_gtk.c of
79 this directory.
80
81 All windows must have a widget, with which they interact with other under-
82 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
83 thw wxWindow class has a member variable called m_widget which holds a
84 pointer to this widget. When the window class represents a GTK native widget,
85 this is (in most cases) the only GTK widget the class manages. E.g. the
86 wxStatitText class handles only a GtkLabel widget a pointer to which you
87 can find in m_widget (defined in wxWindow)
88
89 When the class has a client area for drawing into and for containing children
90 it has to handle the client area widget (of the type GtkMyFixed, defined in
91 win_gtk.c), but there could be any number of widgets, handled by a class
92 The common rule for all windows is only, that the widget that interacts with
93 the rest of GTK must be referenced in m_widget and all other widgets must be
94 children of this widget on the GTK level. The top-most widget, which also
95 represents the client area, must be in the m_wxwindow field and must be of
96 the type GtkMyFixed.
97
98 As I said, the window classes that display a GTK native widget only have
99 one widget, so in the case of e.g. the wxButton class m_widget holds a
100 pointer to a GtkButton widget. But windows with client areas (for drawing
101 and children) have a m_widget field that is a pointer to a GtkScrolled-
102 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
103 one is (in the GTK sense) a child of the GtkScrolledWindow.
104
105 If the m_wxwindow field is set, then all input to this widget is inter-
106 cepted and sent to the wxWindows class. If not, all input to the widget
107 that gets pointed to by m_widget gets intercepted and sent to the class.
108
109 */
110
111 //-----------------------------------------------------------------------------
112 // cond comp
113 //-----------------------------------------------------------------------------
114
115 #if (GTK_MINOR_VERSION == 1)
116 #if (GTK_MICRO_VERSION >= 3)
117 #define NEW_GTK_DND_CODE
118 #endif
119 #endif
120
121 //-----------------------------------------------------------------------------
122 // data
123 //-----------------------------------------------------------------------------
124
125 extern wxList wxPendingDelete;
126 extern wxList wxTopLevelWindows;
127 extern bool g_blockEventsOnDrag;
128 static bool g_capturing = FALSE;
129
130 // hack: we need something to pass to gtk_menu_popup, so we store the time of
131 // the last click here
132 static guint32 gs_timeLastClick = 0;
133
134 //-----------------------------------------------------------------------------
135 // "expose_event" (of m_wxwindow, not of m_widget)
136 //-----------------------------------------------------------------------------
137
138 static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
139 {
140 if (!win->HasVMT()) return;
141 if (g_blockEventsOnDrag) return;
142
143 win->m_updateRegion.Union( gdk_event->area.x,
144 gdk_event->area.y,
145 gdk_event->area.width,
146 gdk_event->area.height );
147
148 if (gdk_event->count > 0) return;
149
150 /*
151 printf( "OnExpose from " );
152 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
153 printf( win->GetClassInfo()->GetClassName() );
154 printf( ".\n" );
155 */
156
157 wxPaintEvent event( win->GetId() );
158 event.SetEventObject( win );
159 win->GetEventHandler()->ProcessEvent( event );
160
161 win->m_updateRegion.Clear();
162 }
163
164 //-----------------------------------------------------------------------------
165 // "draw" (of m_wxwindow, not of m_widget)
166 //-----------------------------------------------------------------------------
167
168 static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxWindow *win )
169 {
170 if (!win->HasVMT()) return;
171 if (g_blockEventsOnDrag) return;
172
173 win->m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
174
175 wxPaintEvent event( win->GetId() );
176 event.SetEventObject( win );
177 win->GetEventHandler()->ProcessEvent( event );
178
179 win->m_updateRegion.Clear();
180 }
181
182 //-----------------------------------------------------------------------------
183 // "key_press_event"
184 //-----------------------------------------------------------------------------
185
186 static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
187 {
188 if (!win->HasVMT()) return FALSE;
189 if (g_blockEventsOnDrag) return FALSE;
190
191 /*
192 printf( "OnKeyPress from " );
193 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
194 printf( win->GetClassInfo()->GetClassName() );
195 printf( ".\n" );
196 */
197
198 long key_code = 0;
199 switch (gdk_event->keyval)
200 {
201 case GDK_BackSpace: key_code = WXK_BACK; break;
202 case GDK_Tab: key_code = WXK_TAB; break;
203 case GDK_Linefeed: key_code = WXK_RETURN; break;
204 case GDK_Clear: key_code = WXK_CLEAR; break;
205 case GDK_Return: key_code = WXK_RETURN; break;
206 case GDK_Pause: key_code = WXK_PAUSE; break;
207 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
208 case GDK_Escape: key_code = WXK_ESCAPE; break;
209 case GDK_Delete: key_code = WXK_DELETE; break;
210 case GDK_Home: key_code = WXK_HOME; break;
211 case GDK_Left: key_code = WXK_LEFT; break;
212 case GDK_Up: key_code = WXK_UP; break;
213 case GDK_Right: key_code = WXK_RIGHT; break;
214 case GDK_Down: key_code = WXK_DOWN; break;
215 case GDK_Prior: key_code = WXK_PRIOR; break;
216 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
217 case GDK_Next: key_code = WXK_NEXT; break;
218 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
219 case GDK_End: key_code = WXK_END; break;
220 case GDK_Begin: key_code = WXK_HOME; break;
221 case GDK_Select: key_code = WXK_SELECT; break;
222 case GDK_Print: key_code = WXK_PRINT; break;
223 case GDK_Execute: key_code = WXK_EXECUTE; break;
224 case GDK_Insert: key_code = WXK_INSERT; break;
225 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
226 case GDK_KP_Tab: key_code = WXK_TAB; break;
227 case GDK_KP_Enter: key_code = WXK_RETURN; break;
228 case GDK_KP_Home: key_code = WXK_HOME; break;
229 case GDK_KP_Left: key_code = WXK_LEFT; break;
230 case GDK_KP_Up: key_code = WXK_UP; break;
231 case GDK_KP_Right: key_code = WXK_RIGHT; break;
232 case GDK_KP_Down: key_code = WXK_DOWN; break;
233 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
234 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
235 case GDK_KP_Next: key_code = WXK_NEXT; break;
236 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
237 case GDK_KP_End: key_code = WXK_END; break;
238 case GDK_KP_Begin: key_code = WXK_HOME; break;
239 case GDK_KP_Insert: key_code = WXK_INSERT; break;
240 case GDK_KP_Delete: key_code = WXK_DELETE; break;
241 case GDK_KP_Multiply: key_code = WXK_MULTIPLY; break;
242 case GDK_KP_Add: key_code = WXK_ADD; break;
243 case GDK_KP_Separator: key_code = WXK_SEPARATOR; break;
244 case GDK_KP_Subtract: key_code = WXK_SUBTRACT; break;
245 case GDK_KP_Decimal: key_code = WXK_DECIMAL; break;
246 case GDK_KP_Divide: key_code = WXK_DIVIDE; break;
247 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
248 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
249 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
250 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
251 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
252 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
253 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
254 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
255 case GDK_KP_8: key_code = WXK_NUMPAD7; break;
256 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
257 case GDK_F1: key_code = WXK_F1; break;
258 case GDK_F2: key_code = WXK_F2; break;
259 case GDK_F3: key_code = WXK_F3; break;
260 case GDK_F4: key_code = WXK_F4; break;
261 case GDK_F5: key_code = WXK_F5; break;
262 case GDK_F6: key_code = WXK_F6; break;
263 case GDK_F7: key_code = WXK_F7; break;
264 case GDK_F8: key_code = WXK_F8; break;
265 case GDK_F9: key_code = WXK_F9; break;
266 case GDK_F10: key_code = WXK_F10; break;
267 case GDK_F11: key_code = WXK_F11; break;
268 case GDK_F12: key_code = WXK_F12; break;
269 default:
270 {
271 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
272 key_code = gdk_event->keyval;
273 }
274 }
275
276 if (!key_code) return FALSE;
277
278 wxKeyEvent event( wxEVT_CHAR );
279 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
280 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
281 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
282 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
283 event.m_keyCode = key_code;
284 event.m_x = 0;
285 event.m_y = 0;
286 event.SetEventObject( win );
287
288 bool ret = win->GetEventHandler()->ProcessEvent( event );
289
290 if (!ret)
291 {
292 wxWindow *ancestor = win;
293 while (ancestor)
294 {
295 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
296 if (command != -1)
297 {
298 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
299 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
300 break;
301 }
302 ancestor = ancestor->GetParent();
303 }
304 }
305
306 if (ret)
307 {
308 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
309 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
310 }
311
312 return ret;
313 }
314
315 //-----------------------------------------------------------------------------
316 // "button_press_event"
317 //-----------------------------------------------------------------------------
318
319 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
320 {
321 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
322
323 if (g_blockEventsOnDrag) return TRUE;
324
325 if (win->m_wxwindow)
326 {
327 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
328 {
329 gtk_widget_grab_focus (win->m_wxwindow);
330
331 /*
332 printf( "GrabFocus from " );
333 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
334 printf( win->GetClassInfo()->GetClassName() );
335 printf( ".\n" );
336 */
337
338 }
339 }
340
341 if (!win->HasVMT()) return TRUE;
342
343 /*
344 printf( "OnButtonPress from " );
345 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
346 printf( win->GetClassInfo()->GetClassName() );
347 printf( ".\n" );
348 */
349
350 wxEventType event_type = wxEVT_LEFT_DOWN;
351
352 if (gdk_event->button == 1)
353 {
354 switch (gdk_event->type)
355 {
356 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
357 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
358 default: break;
359 }
360 }
361 else if (gdk_event->button == 2)
362 {
363 switch (gdk_event->type)
364 {
365 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
366 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
367 default: break;
368 }
369 }
370 else if (gdk_event->button == 3)
371 {
372 switch (gdk_event->type)
373 {
374 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
375 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
376 default: break;
377 }
378 }
379
380 wxMouseEvent event( event_type );
381 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
382 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
383 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
384 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
385 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
386 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
387 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
388
389 event.m_x = (long)gdk_event->x;
390 event.m_y = (long)gdk_event->y;
391
392 // Some control don't have their own X window and thus cannot get
393 // any events.
394
395 if (!g_capturing)
396 {
397 wxNode *node = win->GetChildren()->First();
398 while (node)
399 {
400 wxWindow *child = (wxWindow*)node->Data();
401 if ((child->m_x <= event.m_x) &&
402 (child->m_y <= event.m_y) &&
403 (child->m_x+child->m_width >= event.m_x) &&
404 (child->m_y+child->m_height >= event.m_y))
405 {
406 win = child;
407 event.m_x -= child->m_x;
408 event.m_y -= child->m_y;
409 break;
410 }
411 node = node->Next();
412 }
413 }
414
415 event.SetEventObject( win );
416
417 gs_timeLastClick = gdk_event->time;
418
419 if (win->GetEventHandler()->ProcessEvent( event ))
420 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
421
422 return TRUE;
423 }
424
425 //-----------------------------------------------------------------------------
426 // "button_release_event"
427 //-----------------------------------------------------------------------------
428
429 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
430 {
431 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
432
433 if (g_blockEventsOnDrag) return TRUE;
434
435 if (!win->HasVMT()) return TRUE;
436
437 /*
438 printf( "OnButtonRelease from " );
439 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
440 printf( win->GetClassInfo()->GetClassName() );
441 printf( ".\n" );
442 */
443
444 wxEventType event_type = wxEVT_NULL;
445
446 switch (gdk_event->button)
447 {
448 case 1: event_type = wxEVT_LEFT_UP; break;
449 case 2: event_type = wxEVT_MIDDLE_UP; break;
450 case 3: event_type = wxEVT_RIGHT_UP; break;
451 }
452
453 wxMouseEvent event( event_type );
454 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
455 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
456 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
457 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
458 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
459 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
460 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
461 event.m_x = (long)gdk_event->x;
462 event.m_y = (long)gdk_event->y;
463
464 // Some control don't have their own X window and thus cannot get
465 // any events.
466
467 if (!g_capturing)
468 {
469 wxNode *node = win->GetChildren()->First();
470 while (node)
471 {
472 wxWindow *child = (wxWindow*)node->Data();
473 if ((child->m_x <= event.m_x) &&
474 (child->m_y <= event.m_y) &&
475 (child->m_x+child->m_width >= event.m_x) &&
476 (child->m_y+child->m_height >= event.m_y))
477 {
478 win = child;
479 event.m_x -= child->m_x;
480 event.m_y -= child->m_y;
481 break;
482 }
483 node = node->Next();
484 }
485 }
486
487 event.SetEventObject( win );
488
489 if (win->GetEventHandler()->ProcessEvent( event ))
490 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
491
492 return TRUE;
493 }
494
495 //-----------------------------------------------------------------------------
496 // "motion_notify_event"
497 //-----------------------------------------------------------------------------
498
499 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
500 {
501 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
502
503 if (g_blockEventsOnDrag) return TRUE;
504
505 if (!win->HasVMT()) return TRUE;
506
507 /*
508 printf( "OnMotion from " );
509 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
510 printf( win->GetClassInfo()->GetClassName() );
511 printf( ".\n" );
512 */
513
514 wxMouseEvent event( wxEVT_MOTION );
515 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
516 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
517 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
518 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
519 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
520 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
521 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
522
523 event.m_x = (long)gdk_event->x;
524 event.m_y = (long)gdk_event->y;
525
526 // Some control don't have their own X window and thus cannot get
527 // any events.
528
529 if (!g_capturing)
530 {
531 wxNode *node = win->GetChildren()->First();
532 while (node)
533 {
534 wxWindow *child = (wxWindow*)node->Data();
535 if ((child->m_x <= event.m_x) &&
536 (child->m_y <= event.m_y) &&
537 (child->m_x+child->m_width >= event.m_x) &&
538 (child->m_y+child->m_height >= event.m_y))
539 {
540 win = child;
541 event.m_x -= child->m_x;
542 event.m_y -= child->m_y;
543 break;
544 }
545 node = node->Next();
546 }
547 }
548
549 event.SetEventObject( win );
550
551 if (win->GetEventHandler()->ProcessEvent( event ))
552 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
553
554 return TRUE;
555 }
556
557 //-----------------------------------------------------------------------------
558 // "focus_in_event"
559 //-----------------------------------------------------------------------------
560
561 static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
562 {
563 if (g_blockEventsOnDrag) return TRUE;
564 if (win->m_wxwindow)
565 {
566 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
567 {
568 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
569 /*
570 printf( "SetFocus flag from " );
571 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
572 printf( win->GetClassInfo()->GetClassName() );
573 printf( ".\n" );
574 */
575 }
576 }
577
578 if (!win->HasVMT()) return TRUE;
579
580 /*
581 printf( "OnSetFocus from " );
582 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
583 printf( win->GetClassInfo()->GetClassName() );
584 printf( " " );
585 printf( WXSTRINGCAST win->GetLabel() );
586 printf( ".\n" );
587 */
588
589 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
590 event.SetEventObject( win );
591
592 if (win->GetEventHandler()->ProcessEvent( event ))
593 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
594
595 return TRUE;
596 }
597
598 //-----------------------------------------------------------------------------
599 // "focus_out_event"
600 //-----------------------------------------------------------------------------
601
602 static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
603 {
604 if (g_blockEventsOnDrag) return TRUE;
605 if (win->m_wxwindow)
606 {
607 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
608 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
609 }
610
611 if (!win->HasVMT()) return TRUE;
612
613 /*
614 printf( "OnKillFocus from " );
615 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
616 printf( win->GetClassInfo()->GetClassName() );
617 printf( ".\n" );
618 */
619
620 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
621 event.SetEventObject( win );
622
623 if (win->GetEventHandler()->ProcessEvent( event ))
624 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
625
626 return TRUE;
627 }
628
629 //-----------------------------------------------------------------------------
630 // "enter_notify_event"
631 //-----------------------------------------------------------------------------
632
633 static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
634 {
635 if (widget->window != gdk_event->window) return TRUE;
636
637 if (g_blockEventsOnDrag) return TRUE;
638
639 if (!win->HasVMT()) return TRUE;
640
641 /*
642 printf( "OnEnter from " );
643 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
644 printf( win->GetClassInfo()->GetClassName() );
645 printf( ".\n" );
646 */
647
648 if ((widget->window) && (win->m_cursor))
649 gdk_window_set_cursor( widget->window, win->m_cursor->GetCursor() );
650
651 wxMouseEvent event( wxEVT_ENTER_WINDOW );
652 event.SetEventObject( win );
653
654 if (win->GetEventHandler()->ProcessEvent( event ))
655 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
656
657 return TRUE;
658 }
659
660 //-----------------------------------------------------------------------------
661 // "leave_notify_event"
662 //-----------------------------------------------------------------------------
663
664 static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
665 {
666 if (widget->window != gdk_event->window) return TRUE;
667
668 if (g_blockEventsOnDrag) return TRUE;
669
670 if (!win->HasVMT()) return TRUE;
671
672 /*
673 printf( "OnLeave from " );
674 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
675 printf( win->GetClassInfo()->GetClassName() );
676 printf( ".\n" );
677 */
678
679 if ((widget->window) && (win->m_cursor))
680 gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
681
682 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
683 event.SetEventObject( win );
684
685 if (win->GetEventHandler()->ProcessEvent( event ))
686 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
687
688 return TRUE;
689 }
690
691 //-----------------------------------------------------------------------------
692 // "value_changed" from m_vAdjust
693 //-----------------------------------------------------------------------------
694
695 static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
696 {
697 if (g_blockEventsOnDrag) return;
698
699 /*
700 printf( "OnVScroll from " );
701 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
702 printf( win->GetClassInfo()->GetClassName() );
703 printf( ".\n" );
704 */
705
706 if (!win->HasVMT()) return;
707
708 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
709 if (fabs(diff) < 0.2) return;
710
711 wxEventType command = wxEVT_NULL;
712
713 float line_step = win->m_vAdjust->step_increment;
714 float page_step = win->m_vAdjust->page_increment;
715
716 if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
717 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
718 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
719 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
720 else command = wxEVT_SCROLL_THUMBTRACK;
721
722 int value = (int)(win->m_vAdjust->value+0.5);
723
724 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
725 event.SetEventObject( win );
726 win->GetEventHandler()->ProcessEvent( event );
727 }
728
729 //-----------------------------------------------------------------------------
730 // "value_changed" from m_hAdjust
731 //-----------------------------------------------------------------------------
732
733 static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
734 {
735 if (g_blockEventsOnDrag) return;
736
737 /*
738 printf( "OnHScroll from " );
739 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
740 printf( win->GetClassInfo()->GetClassName() );
741 printf( ".\n" );
742 */
743
744 if (!win->HasVMT()) return;
745
746 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
747 if (fabs(diff) < 0.2) return;
748
749 wxEventType command = wxEVT_NULL;
750
751 float line_step = win->m_hAdjust->step_increment;
752 float page_step = win->m_hAdjust->page_increment;
753
754 if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
755 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
756 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
757 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
758 else command = wxEVT_SCROLL_THUMBTRACK;
759
760 int value = (int)(win->m_hAdjust->value+0.5);
761
762 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
763 event.SetEventObject( win );
764 win->GetEventHandler()->ProcessEvent( event );
765 }
766
767 //-----------------------------------------------------------------------------
768 // "changed" from m_vAdjust
769 //-----------------------------------------------------------------------------
770
771 static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
772 {
773 if (g_blockEventsOnDrag) return;
774
775 /*
776 printf( "OnVScroll change from " );
777 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
778 printf( win->GetClassInfo()->GetClassName() );
779 printf( ".\n" );
780 */
781
782 if (!win->HasVMT()) return;
783
784 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
785 int value = (int)(win->m_vAdjust->value+0.5);
786
787 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
788 event.SetEventObject( win );
789 win->GetEventHandler()->ProcessEvent( event );
790 }
791
792 //-----------------------------------------------------------------------------
793 // "changed" from m_hAdjust
794 //-----------------------------------------------------------------------------
795
796 static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
797 {
798 if (g_blockEventsOnDrag) return;
799
800 /*
801 printf( "OnHScroll change from " );
802 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
803 printf( win->GetClassInfo()->GetClassName() );
804 printf( ".\n" );
805 */
806
807 if (!win->HasVMT()) return;
808
809 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
810 int value = (int)(win->m_hAdjust->value+0.5);
811
812 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
813 event.SetEventObject( win );
814 win->GetEventHandler()->ProcessEvent( event );
815 }
816
817 //-----------------------------------------------------------------------------
818 // "button_press_event" from scrollbar
819 //-----------------------------------------------------------------------------
820
821 static gint gtk_scrollbar_button_press_callback( GtkRange *widget, GdkEventButton *gdk_event, wxWindow *win )
822 {
823 if (gdk_event->window != widget->slider) return FALSE;
824
825 win->m_isScrolling = TRUE;
826
827 return FALSE;
828 }
829
830 //-----------------------------------------------------------------------------
831 // "button_release_event" from scrollbar
832 //-----------------------------------------------------------------------------
833
834 static gint gtk_scrollbar_button_release_callback( GtkRange *widget, GdkEventButton *gdk_event, wxWindow *win )
835 {
836 if (gdk_event->window != widget->slider) return FALSE;
837
838 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(win->m_widget);
839
840 if (widget == GTK_RANGE(s_window->vscrollbar))
841 gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
842 else
843 gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
844
845 win->m_isScrolling = FALSE;
846
847 return FALSE;
848 }
849
850
851 #ifdef NEW_GTK_DND_CODE
852
853 #else
854
855 //-----------------------------------------------------------------------------
856 // "drop_data_available_event"
857 //-----------------------------------------------------------------------------
858
859 static void gtk_window_drop_callback( GtkWidget *widget, GdkEventDropDataAvailable *event, wxWindow *win )
860 {
861 if (!win->HasVMT()) return;
862
863 if (win->GetDropTarget())
864 {
865 int x = 0;
866 int y = 0;
867 gdk_window_get_pointer( widget->window, &x, &y, (GdkModifierType *) NULL );
868
869 printf( "Drop data is of type %s.\n", event->data_type );
870
871 win->GetDropTarget()->OnDrop( x, y, (const void*)event->data, (size_t)event->data_numbytes );
872 }
873
874 /*
875 g_free (event->dropdataavailable.data);
876 g_free (event->dropdataavailable.data_type);
877 */
878 }
879
880 #endif
881 // NEW_GTK_DND_CODE
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 m_hasScrolling = TRUE;
998
999 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
1000
1001 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_press_event",
1002 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1003
1004 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
1005 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1006
1007 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
1008 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1009
1010 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
1011 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1012
1013 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1014 scroll_class->scrollbar_spacing = 0;
1015
1016 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
1017
1018 m_oldHorizontalPos = 0.0;
1019 m_oldVerticalPos = 0.0;
1020
1021 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
1022 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
1023
1024 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1025 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1026 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1027 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1028
1029 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1030 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1031 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1032 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1033
1034 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
1035
1036 if (m_windowStyle & wxRAISED_BORDER)
1037 {
1038 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1039 }
1040 else if (m_windowStyle & wxSUNKEN_BORDER)
1041 {
1042 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1043 }
1044 else
1045 {
1046 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1047 }
1048
1049 m_wxwindow = gtk_myfixed_new();
1050
1051 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
1052
1053 if (m_windowStyle & wxTAB_TRAVERSAL == wxTAB_TRAVERSAL)
1054 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1055 else
1056 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1057
1058 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
1059
1060 // shut the viewport up
1061 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1062 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1063
1064 // I _really_ don't want scrollbars in the beginning
1065 m_vAdjust->lower = 0.0;
1066 m_vAdjust->upper = 1.0;
1067 m_vAdjust->value = 0.0;
1068 m_vAdjust->step_increment = 1.0;
1069 m_vAdjust->page_increment = 1.0;
1070 m_vAdjust->page_size = 5.0;
1071 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1072 m_hAdjust->lower = 0.0;
1073 m_hAdjust->upper = 1.0;
1074 m_hAdjust->value = 0.0;
1075 m_hAdjust->step_increment = 1.0;
1076 m_hAdjust->page_increment = 1.0;
1077 m_hAdjust->page_size = 5.0;
1078 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1079
1080 gtk_widget_show( m_wxwindow );
1081
1082 if (m_parent) m_parent->AddChild( this );
1083
1084 (m_parent->m_insertCallback)( m_parent, this );
1085
1086 PostCreation();
1087
1088 Show( TRUE );
1089
1090 return TRUE;
1091 }
1092
1093 wxWindow::~wxWindow()
1094 {
1095 m_hasVMT = FALSE;
1096
1097 if (m_dropTarget) delete m_dropTarget;
1098
1099 if (m_parent) m_parent->RemoveChild( this );
1100 if (m_widget) Show( FALSE );
1101
1102 DestroyChildren();
1103
1104 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
1105
1106 if (m_scrollGC) gdk_gc_unref( m_scrollGC );
1107
1108 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
1109
1110 if (m_widget) gtk_widget_destroy( m_widget );
1111
1112 if (m_cursor) delete m_cursor;
1113
1114 DeleteRelatedConstraints();
1115 if (m_constraints)
1116 {
1117 // This removes any dangling pointers to this window
1118 // in other windows' constraintsInvolvedIn lists.
1119 UnsetConstraints(m_constraints);
1120 delete m_constraints;
1121 m_constraints = (wxLayoutConstraints *) NULL;
1122 }
1123 if (m_windowSizer)
1124 {
1125 delete m_windowSizer;
1126 m_windowSizer = (wxSizer *) NULL;
1127 }
1128 // If this is a child of a sizer, remove self from parent
1129 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
1130
1131 // Just in case the window has been Closed, but
1132 // we're then deleting immediately: don't leave
1133 // dangling pointers.
1134 wxPendingDelete.DeleteObject(this);
1135
1136 // Just in case we've loaded a top-level window via
1137 // wxWindow::LoadNativeDialog but we weren't a dialog
1138 // class
1139 wxTopLevelWindows.DeleteObject(this);
1140
1141 if (m_windowValidator) delete m_windowValidator;
1142
1143 if (m_clientObject) delete m_clientObject;
1144 }
1145
1146 void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1147 const wxPoint &pos, const wxSize &size,
1148 long style, const wxString &name )
1149 {
1150 if (m_needParent && (parent == NULL))
1151 wxFatalError( "Need complete parent.", name );
1152
1153 m_widget = (GtkWidget*) NULL;
1154 m_wxwindow = (GtkWidget*) NULL;
1155 m_hasVMT = FALSE;
1156 m_parent = parent;
1157 m_children.DeleteContents( FALSE );
1158
1159 m_width = size.x;
1160 if (m_width == -1) m_width = 20;
1161 m_height = size.y;
1162 if (m_height == -1) m_height = 20;
1163
1164 m_x = (int)pos.x;
1165 m_y = (int)pos.y;
1166
1167 if (!m_needParent) // some reasonable defaults
1168 {
1169 if (m_x == -1)
1170 {
1171 m_x = (gdk_screen_width () - m_width) / 2;
1172 if (m_x < 10) m_x = 10;
1173 }
1174 if (m_y == -1)
1175 {
1176 m_y = (gdk_screen_height () - m_height) / 2;
1177 if (m_y < 10) m_y = 10;
1178 }
1179 }
1180
1181 m_minWidth = -1;
1182 m_minHeight = -1;
1183 m_maxWidth = -1;
1184 m_maxHeight = -1;
1185
1186 m_retCode = 0;
1187
1188 m_eventHandler = this;
1189
1190 m_windowId = id;
1191
1192 m_sizeSet = FALSE;
1193
1194 m_cursor = new wxCursor( wxCURSOR_ARROW );
1195 m_font = *wxSWISS_FONT;
1196 // m_backgroundColour = wxWHITE;
1197 // m_foregroundColour = wxBLACK;
1198 m_windowStyle = style;
1199 m_windowName = name;
1200
1201 m_constraints = (wxLayoutConstraints *) NULL;
1202 m_constraintsInvolvedIn = (wxList *) NULL;
1203 m_windowSizer = (wxSizer *) NULL;
1204 m_sizerParent = (wxWindow *) NULL;
1205 m_autoLayout = FALSE;
1206
1207 m_hasScrolling = FALSE;
1208 m_isScrolling = FALSE;
1209 m_hAdjust = (GtkAdjustment *) NULL;
1210 m_vAdjust = (GtkAdjustment *) NULL;
1211 m_oldHorizontalPos = 0.0;
1212 m_oldVerticalPos = 0.0;
1213
1214 m_isShown = FALSE;
1215 m_isEnabled = TRUE;
1216
1217 m_dropTarget = (wxDropTarget *) NULL;
1218 m_resizing = FALSE;
1219 m_windowValidator = (wxValidator *) NULL;
1220 m_scrollGC = (GdkGC*) NULL;
1221 m_widgetStyle = (GtkStyle*) NULL;
1222
1223 m_clientObject = (wxClientData*)NULL;
1224 m_clientData = NULL;
1225 }
1226
1227 void wxWindow::PostCreation()
1228 {
1229 if (m_wxwindow)
1230 {
1231 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1232 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
1233
1234 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1235 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
1236 }
1237
1238 ConnectWidget( GetConnectWidget() );
1239
1240 if (m_widget && m_parent) gtk_widget_realize( m_widget );
1241
1242 if (m_wxwindow) gtk_widget_realize( m_wxwindow );
1243
1244 SetCursor( *wxSTANDARD_CURSOR );
1245
1246 m_hasVMT = TRUE;
1247 }
1248
1249 void wxWindow::ConnectWidget( GtkWidget *widget )
1250 {
1251 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1252 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
1253
1254 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1255 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
1256
1257 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1258 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
1259
1260 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1261 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
1262
1263 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1264 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
1265
1266 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1267 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
1268
1269 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1270 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
1271
1272 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1273 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
1274 }
1275
1276 bool wxWindow::HasVMT()
1277 {
1278 return m_hasVMT;
1279 }
1280
1281 bool wxWindow::Close( bool force )
1282 {
1283 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1284
1285 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1286 event.SetEventObject(this);
1287 event.SetForce(force);
1288
1289 return GetEventHandler()->ProcessEvent(event);
1290 }
1291
1292 bool wxWindow::Destroy()
1293 {
1294 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1295
1296 m_hasVMT = FALSE;
1297 delete this;
1298 return TRUE;
1299 }
1300
1301 bool wxWindow::DestroyChildren()
1302 {
1303 if (GetChildren())
1304 {
1305 wxNode *node;
1306 while ((node = GetChildren()->First()) != (wxNode *)NULL)
1307 {
1308 wxWindow *child;
1309 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
1310 {
1311 delete child;
1312 if (GetChildren()->Member(child)) delete node;
1313 }
1314 }
1315 }
1316 return TRUE;
1317 }
1318
1319 void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1320 {
1321 // are we to set fonts here ?
1322 }
1323
1324 wxPoint wxWindow::GetClientAreaOrigin() const
1325 {
1326 return wxPoint(0,0);
1327 }
1328
1329 void wxWindow::AdjustForParentClientOrigin( int& x, int& y, int sizeFlags )
1330 {
1331 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
1332 {
1333 wxPoint pt(GetParent()->GetClientAreaOrigin());
1334 x += pt.x;
1335 y += pt.y;
1336 }
1337 }
1338
1339 void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
1340 {
1341 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1342 wxASSERT_MSG( (m_parent != NULL), "wxWindow::SetSize requires parent.\n" );
1343
1344 // Don't do anything for children of wxNotebook
1345 if (m_parent->m_wxwindow == NULL) return;
1346
1347 if (m_resizing) return; // I don't like recursions
1348 m_resizing = TRUE;
1349
1350 int old_width = m_width;
1351 int old_height = m_height;
1352
1353 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1354 {
1355 if (x != -1) m_x = x;
1356 if (y != -1) m_y = y;
1357 if (width != -1) m_width = width;
1358 if (height != -1) m_height = height;
1359 }
1360 else
1361 {
1362 m_x = x;
1363 m_y = y;
1364 m_width = width;
1365 m_height = height;
1366 }
1367
1368 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1369 {
1370 if (width == -1) m_width = 80;
1371 }
1372
1373 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1374 {
1375 if (height == -1) m_height = 26;
1376 }
1377
1378 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1379 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
1380 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_minWidth;
1381 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_minHeight;
1382
1383 wxPoint pt( m_parent->GetClientAreaOrigin() );
1384 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x, m_y+pt.y );
1385
1386 if ((old_width != m_width) || (old_height != m_height))
1387 gtk_widget_set_usize( m_widget, m_width, m_height );
1388
1389 m_sizeSet = TRUE;
1390
1391 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1392 event.SetEventObject( this );
1393 ProcessEvent( event );
1394
1395 m_resizing = FALSE;
1396 }
1397
1398 void wxWindow::SetSize( int width, int height )
1399 {
1400 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
1401 }
1402
1403 void wxWindow::Move( int x, int y )
1404 {
1405 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
1406 }
1407
1408 void wxWindow::GetSize( int *width, int *height ) const
1409 {
1410 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1411
1412 if (width) (*width) = m_width;
1413 if (height) (*height) = m_height;
1414 }
1415
1416 void wxWindow::SetClientSize( int width, int height )
1417 {
1418 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1419
1420 if (!m_wxwindow)
1421 {
1422 SetSize( width, height );
1423 }
1424 else
1425 {
1426 int dw = 0;
1427 int dh = 0;
1428
1429 if (!m_hasScrolling)
1430 {
1431 /*
1432 do we have sunken dialogs ?
1433
1434 GtkStyleClass *window_class = m_wxwindow->style->klass;
1435
1436 dw += 2 * window_class->xthickness;
1437 dh += 2 * window_class->ythickness;
1438 */
1439 }
1440 else
1441 {
1442 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1443 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1444
1445 GtkWidget *viewport = scroll_window->viewport;
1446 GtkStyleClass *viewport_class = viewport->style->klass;
1447
1448 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1449 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1450
1451 if ((m_windowStyle & wxRAISED_BORDER) ||
1452 (m_windowStyle & wxSUNKEN_BORDER))
1453 {
1454 dw += 2 * viewport_class->xthickness;
1455 dh += 2 * viewport_class->ythickness;
1456 }
1457
1458 if (GTK_WIDGET_VISIBLE(vscrollbar))
1459 {
1460 dw += vscrollbar->allocation.width;
1461 dw += scroll_class->scrollbar_spacing;
1462 }
1463
1464 if (GTK_WIDGET_VISIBLE(hscrollbar))
1465 {
1466 dh += hscrollbar->allocation.height;
1467 dw += scroll_class->scrollbar_spacing;
1468 }
1469 }
1470
1471 SetSize( width+dw, height+dh );
1472 }
1473 }
1474
1475 void wxWindow::GetClientSize( int *width, int *height ) const
1476 {
1477 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1478
1479 if (!m_wxwindow)
1480 {
1481 if (width) (*width) = m_width;
1482 if (height) (*height) = m_height;
1483 }
1484 else
1485 {
1486 int dw = 0;
1487 int dh = 0;
1488
1489 if (!m_hasScrolling)
1490 {
1491 /*
1492 do we have sunken dialogs ?
1493
1494 GtkStyleClass *window_class = m_wxwindow->style->klass;
1495
1496 dw += 2 * window_class->xthickness;
1497 dh += 2 * window_class->ythickness;
1498 */
1499 }
1500 else
1501 {
1502 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1503 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1504
1505 GtkWidget *viewport = scroll_window->viewport;
1506 GtkStyleClass *viewport_class = viewport->style->klass;
1507
1508 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1509 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1510
1511 if ((m_windowStyle & wxRAISED_BORDER) ||
1512 (m_windowStyle & wxSUNKEN_BORDER))
1513 {
1514 dw += 2 * viewport_class->xthickness;
1515 dh += 2 * viewport_class->ythickness;
1516 }
1517
1518 if (GTK_WIDGET_VISIBLE(vscrollbar))
1519 {
1520 // dw += vscrollbar->allocation.width;
1521 dw += 15; // range.slider_width = 11 + 2*2pts edge
1522 dw += scroll_class->scrollbar_spacing;
1523 }
1524
1525 if (GTK_WIDGET_VISIBLE(hscrollbar))
1526 {
1527 // dh += hscrollbar->allocation.height;
1528 dh += 15;
1529 dh += scroll_class->scrollbar_spacing;
1530 }
1531 }
1532
1533 if (width) (*width) = m_width - dw;
1534 if (height) (*height) = m_height - dh;
1535 }
1536 }
1537
1538 void wxWindow::GetPosition( int *x, int *y ) const
1539 {
1540 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1541
1542 if (x) (*x) = m_x;
1543 if (y) (*y) = m_y;
1544 }
1545
1546 void wxWindow::ClientToScreen( int *x, int *y )
1547 {
1548 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1549
1550 GdkWindow *source = (GdkWindow *) NULL;
1551 if (m_wxwindow)
1552 source = m_wxwindow->window;
1553 else
1554 source = m_widget->window;
1555
1556 int org_x = 0;
1557 int org_y = 0;
1558 gdk_window_get_origin( source, &org_x, &org_y );
1559
1560 if (!m_wxwindow)
1561 {
1562 if (GTK_WIDGET_NO_WINDOW (m_widget))
1563 {
1564 org_x += m_widget->allocation.x;
1565 org_y += m_widget->allocation.y;
1566 }
1567 }
1568
1569 wxPoint pt(GetClientAreaOrigin());
1570 org_x += pt.x;
1571 org_y += pt.y;
1572
1573 if (x) *x += org_x;
1574 if (y) *y += org_y;
1575 }
1576
1577 void wxWindow::ScreenToClient( int *x, int *y )
1578 {
1579 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1580
1581 GdkWindow *source = (GdkWindow *) NULL;
1582 if (m_wxwindow)
1583 source = m_wxwindow->window;
1584 else
1585 source = m_widget->window;
1586
1587 int org_x = 0;
1588 int org_y = 0;
1589 gdk_window_get_origin( source, &org_x, &org_y );
1590
1591 if (!m_wxwindow)
1592 {
1593 if (GTK_WIDGET_NO_WINDOW (m_widget))
1594 {
1595 org_x += m_widget->allocation.x;
1596 org_y += m_widget->allocation.y;
1597 }
1598 }
1599
1600 wxPoint pt(GetClientAreaOrigin());
1601 org_x -= pt.x;
1602 org_y -= pt.y;
1603
1604 if (x) *x -= org_x;
1605 if (y) *y -= org_y;
1606 }
1607
1608 void wxWindow::Centre( int direction )
1609 {
1610 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1611
1612 int x = m_x;
1613 int y = m_y;
1614
1615 if (m_parent)
1616 {
1617 int p_w = 0;
1618 int p_h = 0;
1619 m_parent->GetSize( &p_w, &p_h );
1620 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (p_w - m_width) / 2;
1621 if (direction & wxVERTICAL == wxVERTICAL) y = (p_h - m_height) / 2;
1622 }
1623 else
1624 {
1625 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
1626 if (direction & wxVERTICAL == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
1627 }
1628
1629 Move( x, y );
1630 }
1631
1632 void wxWindow::Fit()
1633 {
1634 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1635
1636 int maxX = 0;
1637 int maxY = 0;
1638 wxNode *node = GetChildren()->First();
1639 while ( node )
1640 {
1641 wxWindow *win = (wxWindow *)node->Data();
1642 int wx, wy, ww, wh;
1643 win->GetPosition(&wx, &wy);
1644 win->GetSize(&ww, &wh);
1645 if ( wx + ww > maxX )
1646 maxX = wx + ww;
1647 if ( wy + wh > maxY )
1648 maxY = wy + wh;
1649
1650 node = node->Next();
1651 }
1652 SetClientSize(maxX + 5, maxY + 10);
1653 }
1654
1655 void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
1656 {
1657 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1658
1659 m_minWidth = minW;
1660 m_minHeight = minH;
1661 m_maxWidth = maxW;
1662 m_maxHeight = maxH;
1663 }
1664
1665 void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
1666 {
1667 //if (GetAutoLayout()) Layout();
1668 }
1669
1670 bool wxWindow::Show( bool show )
1671 {
1672 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1673
1674 if (show)
1675 gtk_widget_show( m_widget );
1676 else
1677 gtk_widget_hide( m_widget );
1678 m_isShown = show;
1679 return TRUE;
1680 }
1681
1682 void wxWindow::Enable( bool enable )
1683 {
1684 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1685
1686 m_isEnabled = enable;
1687 gtk_widget_set_sensitive( m_widget, enable );
1688 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
1689 }
1690
1691 int wxWindow::GetCharHeight() const
1692 {
1693 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1694
1695 if (!m_font.Ok())
1696 {
1697 wxFAIL_MSG( "invalid font" );
1698 return -1;
1699 }
1700
1701 GdkFont *font = m_font.GetInternalFont( 1.0 );
1702 return font->ascent + font->descent;
1703 }
1704
1705 int wxWindow::GetCharWidth() const
1706 {
1707 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1708
1709 if (!m_font.Ok())
1710 {
1711 wxFAIL_MSG( "invalid font" );
1712 return -1;
1713 }
1714
1715 GdkFont *font = m_font.GetInternalFont( 1.0 );
1716 return gdk_string_width( font, "H" );
1717 }
1718
1719 void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
1720 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
1721 {
1722 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1723
1724 wxFont fontToUse = m_font;
1725 if (theFont) fontToUse = *theFont;
1726
1727 if (!fontToUse.Ok())
1728 {
1729 wxFAIL_MSG( "invalid font" );
1730 return;
1731 }
1732 wxASSERT_MSG( (m_font.Ok()), "invalid font" );
1733
1734 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
1735 if (x) (*x) = gdk_string_width( font, string );
1736 if (y) (*y) = font->ascent + font->descent;
1737 if (descent) (*descent) = font->descent;
1738 if (externalLeading) (*externalLeading) = 0; // ??
1739 }
1740
1741 void wxWindow::MakeModal( bool modal )
1742 {
1743 return;
1744 // Disable all other windows
1745 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
1746 {
1747 wxNode *node = wxTopLevelWindows.First();
1748 while (node)
1749 {
1750 wxWindow *win = (wxWindow *)node->Data();
1751 if (win != this)
1752 win->Enable(!modal);
1753
1754 node = node->Next();
1755 }
1756 }
1757 }
1758
1759 void wxWindow::SetFocus()
1760 {
1761 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1762
1763 GtkWidget *connect_widget = GetConnectWidget();
1764 if (connect_widget)
1765 {
1766 if (GTK_WIDGET_CAN_FOCUS(connect_widget) && !GTK_WIDGET_HAS_FOCUS (connect_widget) )
1767 {
1768 gtk_widget_grab_focus (connect_widget);
1769 }
1770 }
1771 }
1772
1773 bool wxWindow::OnClose()
1774 {
1775 return TRUE;
1776 }
1777
1778 void wxWindow::AddChild( wxWindow *child )
1779 {
1780 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1781 wxASSERT_MSG( (child != NULL), "invalid child" );
1782
1783 m_children.Append( child );
1784 }
1785
1786 wxList *wxWindow::GetChildren()
1787 {
1788 return (&m_children);
1789 }
1790
1791 void wxWindow::RemoveChild( wxWindow *child )
1792 {
1793 if (GetChildren()) GetChildren()->DeleteObject( child );
1794 child->m_parent = (wxWindow *) NULL;
1795 }
1796
1797 void wxWindow::SetReturnCode( int retCode )
1798 {
1799 m_retCode = retCode;
1800 }
1801
1802 int wxWindow::GetReturnCode()
1803 {
1804 return m_retCode;
1805 }
1806
1807 void wxWindow::Raise()
1808 {
1809 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1810
1811 if (m_widget) gdk_window_raise( m_widget->window );
1812 }
1813
1814 void wxWindow::Lower()
1815 {
1816 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1817
1818 if (m_widget) gdk_window_lower( m_widget->window );
1819 }
1820
1821 wxEvtHandler *wxWindow::GetEventHandler()
1822 {
1823 return m_eventHandler;
1824 }
1825
1826 void wxWindow::SetEventHandler( wxEvtHandler *handler )
1827 {
1828 m_eventHandler = handler;
1829 }
1830
1831 void wxWindow::PushEventHandler(wxEvtHandler *handler)
1832 {
1833 handler->SetNextHandler(GetEventHandler());
1834 SetEventHandler(handler);
1835 }
1836
1837 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
1838 {
1839 if (GetEventHandler())
1840 {
1841 wxEvtHandler *handlerA = GetEventHandler();
1842 wxEvtHandler *handlerB = handlerA->GetNextHandler();
1843 handlerA->SetNextHandler((wxEvtHandler *) NULL);
1844 SetEventHandler(handlerB);
1845 if (deleteHandler)
1846 {
1847 delete handlerA;
1848 return (wxEvtHandler*) NULL;
1849 }
1850 else
1851 return handlerA;
1852 }
1853 else
1854 return (wxEvtHandler *) NULL;
1855 }
1856
1857 wxValidator *wxWindow::GetValidator()
1858 {
1859 return m_windowValidator;
1860 }
1861
1862 void wxWindow::SetValidator( const wxValidator& validator )
1863 {
1864 if (m_windowValidator) delete m_windowValidator;
1865 m_windowValidator = validator.Clone();
1866 if (m_windowValidator) m_windowValidator->SetWindow(this);
1867 }
1868
1869 void wxWindow::SetClientObject( wxClientData *data )
1870 {
1871 if (m_clientObject) delete m_clientObject;
1872 m_clientObject = data;
1873 }
1874
1875 wxClientData *wxWindow::GetClientObject()
1876 {
1877 return m_clientObject;
1878 }
1879
1880 void wxWindow::SetClientData( void *data )
1881 {
1882 m_clientData = data;
1883 }
1884
1885 void *wxWindow::GetClientData()
1886 {
1887 return m_clientData;
1888 }
1889
1890 bool wxWindow::IsBeingDeleted()
1891 {
1892 return FALSE;
1893 }
1894
1895 void wxWindow::SetId( wxWindowID id )
1896 {
1897 m_windowId = id;
1898 }
1899
1900 wxWindowID wxWindow::GetId()
1901 {
1902 return m_windowId;
1903 }
1904
1905 void wxWindow::SetCursor( const wxCursor &cursor )
1906 {
1907 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1908
1909 if (m_cursor == NULL)
1910 {
1911 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1912 m_cursor = new wxCursor( wxCURSOR_ARROW );
1913 }
1914
1915 if (cursor.Ok())
1916 {
1917 if (*((wxCursor*)&cursor) == m_cursor) return;
1918 *m_cursor = cursor;
1919 }
1920 else
1921 {
1922 *m_cursor = *wxSTANDARD_CURSOR;
1923 }
1924
1925 if ((m_widget) && (m_widget->window))
1926 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
1927
1928 if ((m_wxwindow) && (m_wxwindow->window))
1929 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
1930 }
1931
1932 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
1933 {
1934 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1935
1936 if (eraseBackground && m_wxwindow && m_wxwindow->window)
1937 {
1938 if (rect)
1939 gdk_window_clear_area( m_wxwindow->window,
1940 rect->x,
1941 rect->y,
1942 rect->width,
1943 rect->height );
1944 else
1945 Clear();
1946 }
1947 if (!rect)
1948 {
1949 if (m_wxwindow)
1950 {
1951 int w = 0;
1952 int h = 0;
1953 GetClientSize( &w, &h );
1954
1955 GdkRectangle gdk_rect;
1956 gdk_rect.x = 0;
1957 gdk_rect.y = 0;
1958 gdk_rect.width = w;
1959 gdk_rect.height = h;
1960 gtk_widget_draw( m_wxwindow, &gdk_rect );
1961 }
1962 }
1963 else
1964 {
1965 GdkRectangle gdk_rect;
1966 gdk_rect.x = rect->x;
1967 gdk_rect.y = rect->y;
1968 gdk_rect.width = rect->width;
1969 gdk_rect.height = rect->height;
1970
1971 if (m_wxwindow)
1972 gtk_widget_draw( m_wxwindow, &gdk_rect );
1973 else
1974 gtk_widget_draw( m_widget, &gdk_rect );
1975 }
1976 }
1977
1978 wxRegion wxWindow::GetUpdateRegion() const
1979 {
1980 return m_updateRegion;
1981 }
1982
1983 bool wxWindow::IsExposed( int x, int y) const
1984 {
1985 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
1986 }
1987
1988 bool wxWindow::IsExposed( int x, int y, int w, int h ) const
1989 {
1990 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
1991 }
1992
1993 bool wxWindow::IsExposed( const wxPoint& pt ) const
1994 {
1995 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
1996 }
1997
1998 bool wxWindow::IsExposed( const wxRect& rect ) const
1999 {
2000 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
2001 }
2002
2003 void wxWindow::Clear()
2004 {
2005 wxCHECK_RET( m_widget != NULL, "invalid window" );
2006
2007 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
2008 }
2009
2010 wxColour wxWindow::GetBackgroundColour() const
2011 {
2012 return m_backgroundColour;
2013 }
2014
2015 void wxWindow::SetBackgroundColour( const wxColour &colour )
2016 {
2017 wxCHECK_RET( m_widget != NULL, "invalid window" );
2018
2019 m_backgroundColour = colour;
2020 if (!m_backgroundColour.Ok()) return;
2021
2022 if (m_wxwindow)
2023 {
2024 GdkWindow *window = m_wxwindow->window;
2025 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2026 gdk_window_set_background( window, m_backgroundColour.GetColor() );
2027 gdk_window_clear( window );
2028 }
2029
2030 ApplyWidgetStyle();
2031 }
2032
2033 wxColour wxWindow::GetForegroundColour() const
2034 {
2035 return m_foregroundColour;
2036 }
2037
2038 void wxWindow::SetForegroundColour( const wxColour &colour )
2039 {
2040 wxCHECK_RET( m_widget != NULL, "invalid window" );
2041
2042 m_foregroundColour = colour;
2043 if (!m_foregroundColour.Ok()) return;
2044
2045 ApplyWidgetStyle();
2046 }
2047
2048 GtkStyle *wxWindow::GetWidgetStyle()
2049 {
2050 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
2051
2052 m_widgetStyle =
2053 gtk_style_copy(
2054 gtk_widget_get_style( m_widget ) );
2055
2056 return m_widgetStyle;
2057 }
2058
2059 void wxWindow::SetWidgetStyle()
2060 {
2061 GtkStyle *style = GetWidgetStyle();
2062
2063 gdk_font_unref( style->font );
2064 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2065
2066 if (m_foregroundColour.Ok())
2067 {
2068 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2069 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2070 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2071 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2072 }
2073
2074 if (m_backgroundColour.Ok())
2075 {
2076 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2077 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2078 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2079 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2080 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2081 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2082 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2083 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2084 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2085 }
2086 }
2087
2088 void wxWindow::ApplyWidgetStyle()
2089 {
2090 }
2091
2092 bool wxWindow::Validate()
2093 {
2094 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2095
2096 wxNode *node = GetChildren()->First();
2097 while (node)
2098 {
2099 wxWindow *child = (wxWindow *)node->Data();
2100 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
2101 { return FALSE; }
2102 node = node->Next();
2103 }
2104 return TRUE;
2105 }
2106
2107 bool wxWindow::TransferDataToWindow()
2108 {
2109 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2110
2111 wxNode *node = GetChildren()->First();
2112 while (node)
2113 {
2114 wxWindow *child = (wxWindow *)node->Data();
2115 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2116 !child->GetValidator()->TransferToWindow() )
2117 {
2118 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2119 return FALSE;
2120 }
2121 node = node->Next();
2122 }
2123 return TRUE;
2124 }
2125
2126 bool wxWindow::TransferDataFromWindow()
2127 {
2128 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2129
2130 wxNode *node = GetChildren()->First();
2131 while (node)
2132 {
2133 wxWindow *child = (wxWindow *)node->Data();
2134 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
2135 { return FALSE; }
2136 node = node->Next();
2137 }
2138 return TRUE;
2139 }
2140
2141 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2142 {
2143 m_acceleratorTable = accel;
2144 }
2145
2146 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2147 {
2148 TransferDataToWindow();
2149 }
2150
2151 void wxWindow::InitDialog()
2152 {
2153 wxCHECK_RET( m_widget != NULL, "invalid window" );
2154
2155 wxInitDialogEvent event(GetId());
2156 event.SetEventObject( this );
2157 GetEventHandler()->ProcessEvent(event);
2158 }
2159
2160 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2161 {
2162 menu->SetInvokingWindow( win );
2163 wxNode *node = menu->m_items.First();
2164 while (node)
2165 {
2166 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2167 if (menuitem->IsSubMenu())
2168 SetInvokingWindow( menuitem->GetSubMenu(), win );
2169 node = node->Next();
2170 }
2171 }
2172
2173 bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
2174 {
2175 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2176
2177 wxCHECK_MSG( menu != NULL, FALSE, "invalid popup-menu" );
2178
2179 SetInvokingWindow( menu, this );
2180 gtk_menu_popup(
2181 GTK_MENU(menu->m_menu),
2182 (GtkWidget *)NULL, // parent menu shell
2183 (GtkWidget *)NULL, // parent menu item
2184 (GtkMenuPositionFunc)NULL,
2185 NULL, // client data
2186 0, // button used to activate it
2187 0//gs_timeLastClick // the time of activation
2188 );
2189 return TRUE;
2190 }
2191
2192 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2193 {
2194 wxCHECK_RET( m_widget != NULL, "invalid window" );
2195
2196 GtkWidget *dnd_widget = GetConnectWidget();
2197
2198 DisconnectDnDWidget( dnd_widget );
2199
2200 if (m_dropTarget) delete m_dropTarget;
2201 m_dropTarget = dropTarget;
2202
2203 ConnectDnDWidget( dnd_widget );
2204 }
2205
2206 wxDropTarget *wxWindow::GetDropTarget() const
2207 {
2208 return m_dropTarget;
2209 }
2210
2211 void wxWindow::ConnectDnDWidget( GtkWidget *widget )
2212 {
2213 if (!m_dropTarget) return;
2214
2215 m_dropTarget->RegisterWidget( widget );
2216
2217 #ifdef NEW_GTK_DND_CODE
2218
2219 #else
2220
2221 gtk_signal_connect( GTK_OBJECT(widget), "drop_data_available_event",
2222 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
2223
2224 #endif
2225
2226 }
2227
2228 void wxWindow::DisconnectDnDWidget( GtkWidget *widget )
2229 {
2230 if (!m_dropTarget) return;
2231
2232 #ifdef NEW_GTK_DND_CODE
2233
2234 #else
2235
2236 gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
2237 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
2238
2239 m_dropTarget->UnregisterWidget( widget );
2240
2241 #endif
2242
2243 }
2244
2245 GtkWidget* wxWindow::GetConnectWidget()
2246 {
2247 GtkWidget *connect_widget = m_widget;
2248 if (m_wxwindow) connect_widget = m_wxwindow;
2249
2250 return connect_widget;
2251 }
2252
2253 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2254 {
2255 if (m_wxwindow) return (window == m_wxwindow->window);
2256 return (window == m_widget->window);
2257 }
2258
2259 void wxWindow::SetFont( const wxFont &font )
2260 {
2261 wxCHECK_RET( m_widget != NULL, "invalid window" );
2262
2263 if (((wxFont*)&font)->Ok())
2264 m_font = font;
2265 else
2266 m_font = *wxSWISS_FONT;
2267
2268 ApplyWidgetStyle();
2269 }
2270
2271 wxFont *wxWindow::GetFont()
2272 {
2273 return &m_font;
2274 }
2275
2276 void wxWindow::SetWindowStyleFlag( long flag )
2277 {
2278 m_windowStyle = flag;
2279 }
2280
2281 long wxWindow::GetWindowStyleFlag() const
2282 {
2283 return m_windowStyle;
2284 }
2285
2286 void wxWindow::CaptureMouse()
2287 {
2288 wxCHECK_RET( m_widget != NULL, "invalid window" );
2289
2290 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
2291
2292 GtkWidget *connect_widget = GetConnectWidget();
2293 gtk_grab_add( connect_widget );
2294 gdk_pointer_grab ( connect_widget->window, FALSE,
2295 (GdkEventMask)
2296 (GDK_BUTTON_PRESS_MASK |
2297 GDK_BUTTON_RELEASE_MASK |
2298 GDK_POINTER_MOTION_MASK),
2299 (GdkWindow *) NULL, (GdkCursor *) NULL, GDK_CURRENT_TIME );
2300 g_capturing = TRUE;
2301 }
2302
2303 void wxWindow::ReleaseMouse()
2304 {
2305 wxCHECK_RET( m_widget != NULL, "invalid window" );
2306
2307 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
2308
2309 GtkWidget *connect_widget = GetConnectWidget();
2310 gtk_grab_remove( connect_widget );
2311 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2312 g_capturing = FALSE;
2313 }
2314
2315 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2316 {
2317 }
2318
2319 wxString wxWindow::GetTitle() const
2320 {
2321 return (wxString&)m_windowName;
2322 }
2323
2324 wxString wxWindow::GetLabel() const
2325 {
2326 return GetTitle();
2327 }
2328
2329 void wxWindow::SetName( const wxString &name )
2330 {
2331 m_windowName = name;
2332 }
2333
2334 wxString wxWindow::GetName() const
2335 {
2336 return (wxString&)m_windowName;
2337 }
2338
2339 bool wxWindow::IsShown() const
2340 {
2341 return m_isShown;
2342 }
2343
2344 bool wxWindow::IsRetained()
2345 {
2346 return FALSE;
2347 }
2348
2349 wxWindow *wxWindow::FindWindow( long id )
2350 {
2351 if (id == m_windowId) return this;
2352 wxNode *node = m_children.First();
2353 while (node)
2354 {
2355 wxWindow *child = (wxWindow*)node->Data();
2356 wxWindow *res = child->FindWindow( id );
2357 if (res) return res;
2358 node = node->Next();
2359 }
2360 return (wxWindow *) NULL;
2361 }
2362
2363 wxWindow *wxWindow::FindWindow( const wxString& name )
2364 {
2365 if (name == m_windowName) return this;
2366 wxNode *node = m_children.First();
2367 while (node)
2368 {
2369 wxWindow *child = (wxWindow*)node->Data();
2370 wxWindow *res = child->FindWindow( name );
2371 if (res) return res;
2372 node = node->Next();
2373 }
2374 return (wxWindow *) NULL;
2375 }
2376
2377 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
2378 int range, bool refresh )
2379 {
2380 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2381
2382 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2383
2384 if (!m_wxwindow) return;
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 }