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