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