]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/window.cpp
More colour finetuning
[wxWidgets.git] / src / gtk / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: window.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10
11 #ifdef __GNUG__
12 #pragma implementation "window.h"
13 #endif
14
15 #include "wx/defs.h"
16 #include "wx/window.h"
17 #include "wx/dc.h"
18 #include "wx/frame.h"
19 #include "wx/app.h"
20 #include "wx/layout.h"
21 #include "wx/utils.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
24 #include "wx/dcclient.h"
25 #include "wx/dnd.h"
26 #include "wx/menu.h"
27 #include "wx/statusbr.h"
28 #include "wx/intl.h"
29 #include "wx/settings.h"
30 #include "wx/log.h"
31 #include "gdk/gdkprivate.h"
32 #include "gdk/gdkkeysyms.h"
33
34 #include <math.h>
35
36 //-----------------------------------------------------------------------------
37 // documentation on internals
38 //-----------------------------------------------------------------------------
39
40 /*
41 I have been asked several times about writing some documentation about
42 the GTK port of wxWindows, especially its internal structures. Obviously,
43 you cannot understand wxGTK without knowing a little about the GTK, but
44 some more information about what the wxWindow, which is the base class
45 for all other window classes, does seems required as well.
46
47 What does wxWindow do? It contains the common interface for the following
48 jobs of its descendants:
49
50 1) Define the rudimentary behaviour common to all window classes, such as
51 resizing, intercepting user input (so as to make it possible to use these
52 events for special purposes in a derived class), window names etc.
53
54 2) Provide the possibility to contain and manage children, if the derived
55 class is allowed to contain children, which holds true for those window
56 classes which do not display a native GTK widget. To name them, these
57 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
58 work classes are a special case and are handled a bit differently from
59 the rest. The same holds true for the wxNotebook class.
60
61 3) Provide the possibility to draw into a client area of a window. This,
62 too, only holds true for classes that do not display a native GTK widget
63 as above.
64
65 4) Provide the entire mechanism for scrolling widgets. This actual inter-
66 face for this is usually in wxScrolledWindow, but the GTK implementation
67 is in this class.
68
69 5) A multitude of helper or extra methods for special purposes, such as
70 Drag'n'Drop, managing validators etc.
71
72 Normally one might expect, that one wxWindows window would always correspond
73 to one GTK widget. Under GTK, there is no such allround widget that has all
74 the functionality. Moreover, the GTK defines a client area as a different
75 widget from the actual widget you are handling. Last but not least some
76 special classes (e.g. wxFrame) handle different categories of widgets and
77 still have the possibility to draw something in the client area.
78 It was therefore required to write a special purpose GTK widget, that would
79 represent a client area in the sense of wxWindows capable to do the jobs
80 2), 3) and 4). I have written this class and it resides in win_gtk.c of
81 this directory.
82
83 All windows must have a widget, with which they interact with other under-
84 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
85 thw wxWindow class has a member variable called m_widget which holds a
86 pointer to this widget. When the window class represents a GTK native widget,
87 this is (in most cases) the only GTK widget the class manages. E.g. the
88 wxStatitText class handles only a GtkLabel widget a pointer to which you
89 can find in m_widget (defined in wxWindow)
90
91 When the class has a client area for drawing into and for containing children
92 it has to handle the client area widget (of the type GtkMyFixed, defined in
93 win_gtk.c), but there could be any number of widgets, handled by a class
94 The common rule for all windows is only, that the widget that interacts with
95 the rest of GTK must be referenced in m_widget and all other widgets must be
96 children of this widget on the GTK level. The top-most widget, which also
97 represents the client area, must be in the m_wxwindow field and must be of
98 the type GtkMyFixed.
99
100 As I said, the window classes that display a GTK native widget only have
101 one widget, so in the case of e.g. the wxButton class m_widget holds a
102 pointer to a GtkButton widget. But windows with client areas (for drawing
103 and children) have a m_widget field that is a pointer to a GtkScrolled-
104 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
105 one is (in the GTK sense) a child of the GtkScrolledWindow.
106
107 If the m_wxwindow field is set, then all input to this widget is inter-
108 cepted and sent to the wxWindows class. If not, all input to the widget
109 that gets pointed to by m_widget gets intercepted and sent to the class.
110
111 */
112
113 //-------------------------------------------------------------------------
114 // conditional compilation
115 //-------------------------------------------------------------------------
116
117 #if (GTK_MINOR_VERSION == 1)
118 #if (GTK_MICRO_VERSION >= 5)
119 #define NEW_GTK_SCROLL_CODE
120 #endif
121 #endif
122
123 //-----------------------------------------------------------------------------
124 // data
125 //-----------------------------------------------------------------------------
126
127 extern wxList wxPendingDelete;
128 extern wxList wxTopLevelWindows;
129 extern bool g_blockEventsOnDrag;
130 extern bool g_blockEventsOnScroll;
131 static bool g_capturing = FALSE;
132
133 // hack: we need something to pass to gtk_menu_popup, so we store the time of
134 // the last click here
135 static guint32 gs_timeLastClick = 0;
136
137 //-----------------------------------------------------------------------------
138 // "expose_event" (of m_wxwindow, not of m_widget)
139 //-----------------------------------------------------------------------------
140
141 static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
142 {
143 if (!win->HasVMT()) return;
144
145 win->m_updateRegion.Union( gdk_event->area.x,
146 gdk_event->area.y,
147 gdk_event->area.width,
148 gdk_event->area.height );
149
150 if (gdk_event->count > 0) return;
151
152 /*
153 printf( "OnExpose from " );
154 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
155 printf( win->GetClassInfo()->GetClassName() );
156 printf( ".\n" );
157 */
158
159 wxPaintEvent event( win->GetId() );
160 event.SetEventObject( win );
161 win->GetEventHandler()->ProcessEvent( event );
162
163 win->m_updateRegion.Clear();
164 }
165
166 //-----------------------------------------------------------------------------
167 // "draw" (of m_wxwindow, not of m_widget)
168 //-----------------------------------------------------------------------------
169
170 static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxWindow *win )
171 {
172 if (!win->HasVMT()) return;
173
174 win->m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
175
176 wxPaintEvent event( win->GetId() );
177 event.SetEventObject( win );
178 win->GetEventHandler()->ProcessEvent( event );
179
180 win->m_updateRegion.Clear();
181 }
182
183 //-----------------------------------------------------------------------------
184 // "key_press_event"
185 //-----------------------------------------------------------------------------
186
187 static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
188 {
189 if (!win->HasVMT()) return FALSE;
190 if (g_blockEventsOnDrag) return FALSE;
191
192 /*
193 printf( "OnKeyPress from " );
194 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
195 printf( win->GetClassInfo()->GetClassName() );
196 printf( ".\n" );
197 */
198
199 long key_code = 0;
200 switch (gdk_event->keyval)
201 {
202 case GDK_BackSpace: key_code = WXK_BACK; break;
203 case GDK_Tab: key_code = WXK_TAB; break;
204 case GDK_Linefeed: key_code = WXK_RETURN; break;
205 case GDK_Clear: key_code = WXK_CLEAR; break;
206 case GDK_Return: key_code = WXK_RETURN; break;
207 case GDK_Pause: key_code = WXK_PAUSE; break;
208 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
209 case GDK_Escape: key_code = WXK_ESCAPE; break;
210 case GDK_Delete: key_code = WXK_DELETE; break;
211 case GDK_Home: key_code = WXK_HOME; break;
212 case GDK_Left: key_code = WXK_LEFT; break;
213 case GDK_Up: key_code = WXK_UP; break;
214 case GDK_Right: key_code = WXK_RIGHT; break;
215 case GDK_Down: key_code = WXK_DOWN; break;
216 case GDK_Prior: key_code = WXK_PRIOR; break;
217 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
218 case GDK_Next: key_code = WXK_NEXT; break;
219 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
220 case GDK_End: key_code = WXK_END; break;
221 case GDK_Begin: key_code = WXK_HOME; break;
222 case GDK_Select: key_code = WXK_SELECT; break;
223 case GDK_Print: key_code = WXK_PRINT; break;
224 case GDK_Execute: key_code = WXK_EXECUTE; break;
225 case GDK_Insert: key_code = WXK_INSERT; break;
226 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
227 case GDK_KP_Tab: key_code = WXK_TAB; break;
228 case GDK_KP_Enter: key_code = WXK_RETURN; break;
229 case GDK_KP_Home: key_code = WXK_HOME; break;
230 case GDK_KP_Left: key_code = WXK_LEFT; break;
231 case GDK_KP_Up: key_code = WXK_UP; break;
232 case GDK_KP_Right: key_code = WXK_RIGHT; break;
233 case GDK_KP_Down: key_code = WXK_DOWN; break;
234 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
235 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
236 case GDK_KP_Next: key_code = WXK_NEXT; break;
237 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
238 case GDK_KP_End: key_code = WXK_END; break;
239 case GDK_KP_Begin: key_code = WXK_HOME; break;
240 case GDK_KP_Insert: key_code = WXK_INSERT; break;
241 case GDK_KP_Delete: key_code = WXK_DELETE; break;
242 case GDK_KP_Multiply: key_code = WXK_MULTIPLY; break;
243 case GDK_KP_Add: key_code = WXK_ADD; break;
244 case GDK_KP_Separator: key_code = WXK_SEPARATOR; break;
245 case GDK_KP_Subtract: key_code = WXK_SUBTRACT; break;
246 case GDK_KP_Decimal: key_code = WXK_DECIMAL; break;
247 case GDK_KP_Divide: key_code = WXK_DIVIDE; break;
248 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
249 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
250 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
251 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
252 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
253 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
254 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
255 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
256 case GDK_KP_8: key_code = WXK_NUMPAD7; break;
257 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
258 case GDK_F1: key_code = WXK_F1; break;
259 case GDK_F2: key_code = WXK_F2; break;
260 case GDK_F3: key_code = WXK_F3; break;
261 case GDK_F4: key_code = WXK_F4; break;
262 case GDK_F5: key_code = WXK_F5; break;
263 case GDK_F6: key_code = WXK_F6; break;
264 case GDK_F7: key_code = WXK_F7; break;
265 case GDK_F8: key_code = WXK_F8; break;
266 case GDK_F9: key_code = WXK_F9; break;
267 case GDK_F10: key_code = WXK_F10; break;
268 case GDK_F11: key_code = WXK_F11; break;
269 case GDK_F12: key_code = WXK_F12; break;
270 default:
271 {
272 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
273 key_code = gdk_event->keyval;
274 }
275 }
276
277 if (!key_code) return FALSE;
278
279 wxKeyEvent event( wxEVT_CHAR );
280 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
281 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
282 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
283 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
284 event.m_keyCode = key_code;
285 event.m_x = 0;
286 event.m_y = 0;
287 event.SetEventObject( win );
288
289 bool ret = win->GetEventHandler()->ProcessEvent( event );
290
291 if (!ret)
292 {
293 wxWindow *ancestor = win;
294 while (ancestor)
295 {
296 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
297 if (command != -1)
298 {
299 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
300 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
301 break;
302 }
303 ancestor = ancestor->GetParent();
304 }
305 }
306
307 if (ret)
308 {
309 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
310 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
311 }
312
313 return ret;
314 }
315
316 //-----------------------------------------------------------------------------
317 // "button_press_event"
318 //-----------------------------------------------------------------------------
319
320 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
321 {
322 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
323
324 if (g_blockEventsOnDrag) return TRUE;
325 if (g_blockEventsOnScroll) return TRUE;
326
327 if (win->m_wxwindow)
328 {
329 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
330 {
331 gtk_widget_grab_focus (win->m_wxwindow);
332
333 /*
334 printf( "GrabFocus from " );
335 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
336 printf( win->GetClassInfo()->GetClassName() );
337 printf( ".\n" );
338 */
339
340 }
341 }
342
343 if (!win->HasVMT()) return TRUE;
344
345 /*
346 printf( "OnButtonPress from " );
347 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
348 printf( win->GetClassInfo()->GetClassName() );
349 printf( ".\n" );
350 */
351
352 wxEventType event_type = wxEVT_LEFT_DOWN;
353
354 if (gdk_event->button == 1)
355 {
356 switch (gdk_event->type)
357 {
358 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
359 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
360 default: break;
361 }
362 }
363 else if (gdk_event->button == 2)
364 {
365 switch (gdk_event->type)
366 {
367 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
368 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
369 default: break;
370 }
371 }
372 else if (gdk_event->button == 3)
373 {
374 switch (gdk_event->type)
375 {
376 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
377 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
378 default: break;
379 }
380 }
381
382 wxMouseEvent event( event_type );
383 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
384 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
385 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
386 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
387 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
388 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
389 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
390
391 event.m_x = (long)gdk_event->x;
392 event.m_y = (long)gdk_event->y;
393
394 // Some control don't have their own X window and thus cannot get
395 // any events.
396
397 if (!g_capturing)
398 {
399 wxNode *node = win->GetChildren().First();
400 while (node)
401 {
402 wxWindow *child = (wxWindow*)node->Data();
403
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 m_backgroundColour = colour;
2168 if (!m_backgroundColour.Ok()) return;
2169
2170 if (m_wxwindow)
2171 {
2172 GdkWindow *window = m_wxwindow->window;
2173 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2174 gdk_window_set_background( window, m_backgroundColour.GetColor() );
2175 gdk_window_clear( window );
2176 }
2177
2178 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2179 if (sysbg.Red() == colour.Red() &&
2180 sysbg.Green() == colour.Green() &&
2181 sysbg.Blue() == colour.Blue())
2182 {
2183 m_backgroundColour = wxNullColour;
2184 ApplyWidgetStyle();
2185 m_backgroundColour = sysbg;
2186 }
2187 else
2188 {
2189 ApplyWidgetStyle();
2190 }
2191 }
2192
2193 wxColour wxWindow::GetForegroundColour() const
2194 {
2195 return m_foregroundColour;
2196 }
2197
2198 void wxWindow::SetForegroundColour( const wxColour &colour )
2199 {
2200 wxCHECK_RET( m_widget != NULL, "invalid window" );
2201
2202 if (m_foregroundColour == colour) return;
2203
2204 m_foregroundColour = colour;
2205 if (!m_foregroundColour.Ok()) return;
2206
2207 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2208 if (sysbg.Red() == colour.Red() &&
2209 sysbg.Green() == colour.Green() &&
2210 sysbg.Blue() == colour.Blue())
2211 {
2212 m_backgroundColour = wxNullColour;
2213 ApplyWidgetStyle();
2214 m_backgroundColour = sysbg;
2215 }
2216 else
2217 {
2218 ApplyWidgetStyle();
2219 }
2220 }
2221
2222 GtkStyle *wxWindow::GetWidgetStyle()
2223 {
2224 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
2225
2226 m_widgetStyle =
2227 gtk_style_copy(
2228 gtk_widget_get_style( m_widget ) );
2229
2230 return m_widgetStyle;
2231 }
2232
2233 void wxWindow::SetWidgetStyle()
2234 {
2235 GtkStyle *style = GetWidgetStyle();
2236
2237 gdk_font_unref( style->font );
2238 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2239
2240 if (m_foregroundColour.Ok())
2241 {
2242 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2243 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2244 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2245 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2246 }
2247
2248 if (m_backgroundColour.Ok())
2249 {
2250 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2251 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2252 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2253 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2254 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2255 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2256 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2257 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2258 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2259 }
2260 }
2261
2262 void wxWindow::ApplyWidgetStyle()
2263 {
2264 }
2265
2266 bool wxWindow::Validate()
2267 {
2268 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2269
2270 wxNode *node = m_children.First();
2271 while (node)
2272 {
2273 wxWindow *child = (wxWindow *)node->Data();
2274 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
2275 {
2276 return FALSE;
2277 }
2278 node = node->Next();
2279 }
2280 return TRUE;
2281 }
2282
2283 bool wxWindow::TransferDataToWindow()
2284 {
2285 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2286
2287 wxNode *node = m_children.First();
2288 while (node)
2289 {
2290 wxWindow *child = (wxWindow *)node->Data();
2291 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2292 !child->GetValidator()->TransferToWindow() )
2293 {
2294 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2295 return FALSE;
2296 }
2297 node = node->Next();
2298 }
2299 return TRUE;
2300 }
2301
2302 bool wxWindow::TransferDataFromWindow()
2303 {
2304 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2305
2306 wxNode *node = m_children.First();
2307 while (node)
2308 {
2309 wxWindow *child = (wxWindow *)node->Data();
2310 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
2311 {
2312 return FALSE;
2313 }
2314 node = node->Next();
2315 }
2316 return TRUE;
2317 }
2318
2319 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2320 {
2321 m_acceleratorTable = accel;
2322 }
2323
2324 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2325 {
2326 TransferDataToWindow();
2327 }
2328
2329 void wxWindow::InitDialog()
2330 {
2331 wxCHECK_RET( m_widget != NULL, "invalid window" );
2332
2333 wxInitDialogEvent event(GetId());
2334 event.SetEventObject( this );
2335 GetEventHandler()->ProcessEvent(event);
2336 }
2337
2338 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2339 {
2340 menu->SetInvokingWindow( win );
2341 wxNode *node = menu->m_items.First();
2342 while (node)
2343 {
2344 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2345 if (menuitem->IsSubMenu())
2346 {
2347 SetInvokingWindow( menuitem->GetSubMenu(), win );
2348 }
2349 node = node->Next();
2350 }
2351 }
2352
2353 bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
2354 {
2355 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2356
2357 wxCHECK_MSG( menu != NULL, FALSE, "invalid popup-menu" );
2358
2359 SetInvokingWindow( menu, this );
2360 gtk_menu_popup(
2361 GTK_MENU(menu->m_menu),
2362 (GtkWidget *)NULL, // parent menu shell
2363 (GtkWidget *)NULL, // parent menu item
2364 (GtkMenuPositionFunc)NULL,
2365 NULL, // client data
2366 0, // button used to activate it
2367 0//gs_timeLastClick // the time of activation
2368 );
2369 return TRUE;
2370 }
2371
2372 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2373 {
2374 wxCHECK_RET( m_widget != NULL, "invalid window" );
2375
2376 GtkWidget *dnd_widget = GetConnectWidget();
2377
2378 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
2379
2380 if (m_dropTarget) delete m_dropTarget;
2381 m_dropTarget = dropTarget;
2382
2383 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
2384 }
2385
2386 wxDropTarget *wxWindow::GetDropTarget() const
2387 {
2388 return m_dropTarget;
2389 }
2390
2391 GtkWidget* wxWindow::GetConnectWidget()
2392 {
2393 GtkWidget *connect_widget = m_widget;
2394 if (m_wxwindow) connect_widget = m_wxwindow;
2395
2396 return connect_widget;
2397 }
2398
2399 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2400 {
2401 if (m_wxwindow) return (window == m_wxwindow->window);
2402 return (window == m_widget->window);
2403 }
2404
2405 void wxWindow::SetFont( const wxFont &font )
2406 {
2407 wxCHECK_RET( m_widget != NULL, "invalid window" );
2408
2409 if (((wxFont*)&font)->Ok())
2410 m_font = font;
2411 else
2412 m_font = *wxSWISS_FONT;
2413
2414 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2415 if (sysbg.Red() == m_backgroundColour.Red() &&
2416 sysbg.Green() == m_backgroundColour.Green() &&
2417 sysbg.Blue() == m_backgroundColour.Blue())
2418 {
2419 m_backgroundColour = wxNullColour;
2420 ApplyWidgetStyle();
2421 m_backgroundColour = sysbg;
2422 }
2423 else
2424 {
2425 ApplyWidgetStyle();
2426 }
2427 }
2428
2429 void wxWindow::SetWindowStyleFlag( long flag )
2430 {
2431 m_windowStyle = flag;
2432 }
2433
2434 long wxWindow::GetWindowStyleFlag() const
2435 {
2436 return m_windowStyle;
2437 }
2438
2439 void wxWindow::CaptureMouse()
2440 {
2441 wxCHECK_RET( m_widget != NULL, "invalid window" );
2442
2443 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
2444
2445 GtkWidget *connect_widget = GetConnectWidget();
2446 gtk_grab_add( connect_widget );
2447 gdk_pointer_grab( connect_widget->window, FALSE,
2448 (GdkEventMask)
2449 (GDK_BUTTON_PRESS_MASK |
2450 GDK_BUTTON_RELEASE_MASK |
2451 GDK_POINTER_MOTION_MASK),
2452 (GdkWindow *) NULL,
2453 (GdkCursor *) NULL,
2454 GDK_CURRENT_TIME );
2455 g_capturing = TRUE;
2456 }
2457
2458 void wxWindow::ReleaseMouse()
2459 {
2460 wxCHECK_RET( m_widget != NULL, "invalid window" );
2461
2462 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
2463
2464 GtkWidget *connect_widget = GetConnectWidget();
2465 gtk_grab_remove( connect_widget );
2466 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2467 g_capturing = FALSE;
2468 }
2469
2470 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2471 {
2472 }
2473
2474 wxString wxWindow::GetTitle() const
2475 {
2476 return (wxString&)m_windowName;
2477 }
2478
2479 wxString wxWindow::GetLabel() const
2480 {
2481 return GetTitle();
2482 }
2483
2484 void wxWindow::SetName( const wxString &name )
2485 {
2486 m_windowName = name;
2487 }
2488
2489 wxString wxWindow::GetName() const
2490 {
2491 return (wxString&)m_windowName;
2492 }
2493
2494 bool wxWindow::IsShown() const
2495 {
2496 return m_isShown;
2497 }
2498
2499 bool wxWindow::IsRetained()
2500 {
2501 return FALSE;
2502 }
2503
2504 wxWindow *wxWindow::FindWindow( long id )
2505 {
2506 if (id == m_windowId) return this;
2507 wxNode *node = m_children.First();
2508 while (node)
2509 {
2510 wxWindow *child = (wxWindow*)node->Data();
2511 wxWindow *res = child->FindWindow( id );
2512 if (res) return res;
2513 node = node->Next();
2514 }
2515 return (wxWindow *) NULL;
2516 }
2517
2518 wxWindow *wxWindow::FindWindow( const wxString& name )
2519 {
2520 if (name == m_windowName) return this;
2521 wxNode *node = m_children.First();
2522 while (node)
2523 {
2524 wxWindow *child = (wxWindow*)node->Data();
2525 wxWindow *res = child->FindWindow( name );
2526 if (res) return res;
2527 node = node->Next();
2528 }
2529 return (wxWindow *) NULL;
2530 }
2531
2532 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
2533 int range, bool refresh )
2534 {
2535 wxCHECK_RET( m_widget != NULL, "invalid window" );
2536
2537 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
2538
2539 m_hasScrolling = TRUE;
2540
2541 if (orient == wxHORIZONTAL)
2542 {
2543 float fpos = (float)pos;
2544 float frange = (float)range;
2545 float fthumb = (float)thumbVisible;
2546 if (fpos > frange-fthumb) fpos = frange-fthumb;
2547 if (fpos < 0.0) fpos = 0.0;
2548
2549 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2550 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2551 {
2552 SetScrollPos( orient, pos, refresh );
2553 return;
2554 }
2555
2556 m_oldHorizontalPos = fpos;
2557
2558 m_hAdjust->lower = 0.0;
2559 m_hAdjust->upper = frange;
2560 m_hAdjust->value = fpos;
2561 m_hAdjust->step_increment = 1.0;
2562 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2563 m_hAdjust->page_size = fthumb;
2564 }
2565 else
2566 {
2567 float fpos = (float)pos;
2568 float frange = (float)range;
2569 float fthumb = (float)thumbVisible;
2570 if (fpos > frange-fthumb) fpos = frange-fthumb;
2571 if (fpos < 0.0) fpos = 0.0;
2572
2573 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2574 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2575 {
2576 SetScrollPos( orient, pos, refresh );
2577 return;
2578 }
2579
2580 m_oldVerticalPos = fpos;
2581
2582 m_vAdjust->lower = 0.0;
2583 m_vAdjust->upper = frange;
2584 m_vAdjust->value = fpos;
2585 m_vAdjust->step_increment = 1.0;
2586 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2587 m_vAdjust->page_size = fthumb;
2588 }
2589
2590 if (m_wxwindow->window)
2591 {
2592 if (orient == wxHORIZONTAL)
2593 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2594 else
2595 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2596
2597 gtk_widget_set_usize( m_widget, m_width, m_height );
2598 }
2599 }
2600
2601 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
2602 {
2603 wxCHECK_RET( m_widget != NULL, "invalid window" );
2604
2605 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
2606
2607 if (orient == wxHORIZONTAL)
2608 {
2609 float fpos = (float)pos;
2610 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
2611 if (fpos < 0.0) fpos = 0.0;
2612 m_oldHorizontalPos = fpos;
2613
2614 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2615 m_hAdjust->value = fpos;
2616 }
2617 else
2618 {
2619 float fpos = (float)pos;
2620 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
2621 if (fpos < 0.0) fpos = 0.0;
2622 m_oldVerticalPos = fpos;
2623
2624 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2625 m_vAdjust->value = fpos;
2626 }
2627
2628 if (!m_isScrolling)
2629 {
2630 if (m_wxwindow->window)
2631 {
2632 if (orient == wxHORIZONTAL)
2633 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2634 else
2635 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2636 }
2637 }
2638 }
2639
2640 int wxWindow::GetScrollThumb( int orient ) const
2641 {
2642 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
2643
2644 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
2645
2646 if (orient == wxHORIZONTAL)
2647 return (int)(m_hAdjust->page_size+0.5);
2648 else
2649 return (int)(m_vAdjust->page_size+0.5);
2650 }
2651
2652 int wxWindow::GetScrollPos( int orient ) const
2653 {
2654 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
2655
2656 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
2657
2658 if (orient == wxHORIZONTAL)
2659 return (int)(m_hAdjust->value+0.5);
2660 else
2661 return (int)(m_vAdjust->value+0.5);
2662 }
2663
2664 int wxWindow::GetScrollRange( int orient ) const
2665 {
2666 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
2667
2668 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
2669
2670 if (orient == wxHORIZONTAL)
2671 return (int)(m_hAdjust->upper+0.5);
2672 else
2673 return (int)(m_vAdjust->upper+0.5);
2674 }
2675
2676 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
2677 {
2678 wxCHECK_RET( m_widget != NULL, "invalid window" );
2679
2680 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
2681
2682 int cw = 0;
2683 int ch = 0;
2684 GetClientSize( &cw, &ch );
2685
2686 int w = cw - abs(dx);
2687 int h = ch - abs(dy);
2688 if ((h < 0) || (w < 0))
2689 {
2690 Refresh();
2691 return;
2692 }
2693 int s_x = 0;
2694 int s_y = 0;
2695 if (dx < 0) s_x = -dx;
2696 if (dy < 0) s_y = -dy;
2697 int d_x = 0;
2698 int d_y = 0;
2699 if (dx > 0) d_x = dx;
2700 if (dy > 0) d_y = dy;
2701
2702 if (!m_scrollGC)
2703 {
2704 m_scrollGC = gdk_gc_new( m_wxwindow->window );
2705 gdk_gc_set_exposures( m_scrollGC, TRUE );
2706 }
2707
2708 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
2709 m_wxwindow->window, s_x, s_y, w, h );
2710
2711 wxRect rect;
2712 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2713 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2714 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2715 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
2716
2717 Refresh( TRUE, &rect );
2718 }
2719
2720 //-------------------------------------------------------------------------------------
2721 // Layout
2722 //-------------------------------------------------------------------------------------
2723
2724 wxLayoutConstraints *wxWindow::GetConstraints() const
2725 {
2726 return m_constraints;
2727 }
2728
2729 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
2730 {
2731 if (m_constraints)
2732 {
2733 UnsetConstraints(m_constraints);
2734 delete m_constraints;
2735 }
2736 m_constraints = constraints;
2737 if (m_constraints)
2738 {
2739 // Make sure other windows know they're part of a 'meaningful relationship'
2740 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
2741 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2742 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
2743 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2744 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
2745 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2746 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
2747 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2748 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
2749 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2750 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
2751 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2752 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
2753 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2754 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
2755 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2756 }
2757 ;
2758 }
2759 ;
2760
2761 void wxWindow::SetAutoLayout( bool autoLayout )
2762 {
2763 m_autoLayout = autoLayout;
2764 }
2765
2766 bool wxWindow::GetAutoLayout() const
2767 {
2768 return m_autoLayout;
2769 }
2770
2771 wxSizer *wxWindow::GetSizer() const
2772 {
2773 return m_windowSizer;
2774 }
2775
2776 void wxWindow::SetSizerParent( wxWindow *win )
2777 {
2778 m_sizerParent = win;
2779 }
2780
2781 wxWindow *wxWindow::GetSizerParent() const
2782 {
2783 return m_sizerParent;
2784 }
2785
2786 // This removes any dangling pointers to this window
2787 // in other windows' constraintsInvolvedIn lists.
2788 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
2789 {
2790 if (c)
2791 {
2792 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2793 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2794 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2795 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2796 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
2797 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2798 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
2799 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2800 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
2801 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2802 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
2803 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2804 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
2805 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2806 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
2807 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2808 }
2809 }
2810
2811 // Back-pointer to other windows we're involved with, so if we delete
2812 // this window, we must delete any constraints we're involved with.
2813 void wxWindow::AddConstraintReference(wxWindow *otherWin)
2814 {
2815 if (!m_constraintsInvolvedIn)
2816 m_constraintsInvolvedIn = new wxList;
2817 if (!m_constraintsInvolvedIn->Member(otherWin))
2818 m_constraintsInvolvedIn->Append(otherWin);
2819 }
2820
2821 // REMOVE back-pointer to other windows we're involved with.
2822 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
2823 {
2824 if (m_constraintsInvolvedIn)
2825 m_constraintsInvolvedIn->DeleteObject(otherWin);
2826 }
2827
2828 // Reset any constraints that mention this window
2829 void wxWindow::DeleteRelatedConstraints()
2830 {
2831 if (m_constraintsInvolvedIn)
2832 {
2833 wxNode *node = m_constraintsInvolvedIn->First();
2834 while (node)
2835 {
2836 wxWindow *win = (wxWindow *)node->Data();
2837 wxNode *next = node->Next();
2838 wxLayoutConstraints *constr = win->GetConstraints();
2839
2840 // Reset any constraints involving this window
2841 if (constr)
2842 {
2843 constr->left.ResetIfWin((wxWindow *)this);
2844 constr->top.ResetIfWin((wxWindow *)this);
2845 constr->right.ResetIfWin((wxWindow *)this);
2846 constr->bottom.ResetIfWin((wxWindow *)this);
2847 constr->width.ResetIfWin((wxWindow *)this);
2848 constr->height.ResetIfWin((wxWindow *)this);
2849 constr->centreX.ResetIfWin((wxWindow *)this);
2850 constr->centreY.ResetIfWin((wxWindow *)this);
2851 }
2852 delete node;
2853 node = next;
2854 }
2855 delete m_constraintsInvolvedIn;
2856 m_constraintsInvolvedIn = (wxList *) NULL;
2857 }
2858 }
2859
2860 void wxWindow::SetSizer(wxSizer *sizer)
2861 {
2862 m_windowSizer = sizer;
2863 if (sizer)
2864 sizer->SetSizerParent((wxWindow *)this);
2865 }
2866
2867 /*
2868 * New version
2869 */
2870
2871 bool wxWindow::Layout()
2872 {
2873 if (GetConstraints())
2874 {
2875 int w, h;
2876 GetClientSize(&w, &h);
2877 GetConstraints()->width.SetValue(w);
2878 GetConstraints()->height.SetValue(h);
2879 }
2880
2881 // If top level (one sizer), evaluate the sizer's constraints.
2882 if (GetSizer())
2883 {
2884 int noChanges;
2885 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2886 GetSizer()->LayoutPhase1(&noChanges);
2887 GetSizer()->LayoutPhase2(&noChanges);
2888 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2889 return TRUE;
2890 }
2891 else
2892 {
2893 // Otherwise, evaluate child constraints
2894 ResetConstraints(); // Mark all constraints as unevaluated
2895 DoPhase(1); // Just one phase need if no sizers involved
2896 DoPhase(2);
2897 SetConstraintSizes(); // Recursively set the real window sizes
2898 }
2899 return TRUE;
2900 }
2901
2902
2903 // Do a phase of evaluating constraints:
2904 // the default behaviour. wxSizers may do a similar
2905 // thing, but also impose their own 'constraints'
2906 // and order the evaluation differently.
2907 bool wxWindow::LayoutPhase1(int *noChanges)
2908 {
2909 wxLayoutConstraints *constr = GetConstraints();
2910 if (constr)
2911 {
2912 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
2913 }
2914 else
2915 return TRUE;
2916 }
2917
2918 bool wxWindow::LayoutPhase2(int *noChanges)
2919 {
2920 *noChanges = 0;
2921
2922 // Layout children
2923 DoPhase(1);
2924 DoPhase(2);
2925 return TRUE;
2926 }
2927
2928 // Do a phase of evaluating child constraints
2929 bool wxWindow::DoPhase(int phase)
2930 {
2931 int noIterations = 0;
2932 int maxIterations = 500;
2933 int noChanges = 1;
2934 int noFailures = 0;
2935 wxList succeeded;
2936 while ((noChanges > 0) && (noIterations < maxIterations))
2937 {
2938 noChanges = 0;
2939 noFailures = 0;
2940 wxNode *node = m_children.First();
2941 while (node)
2942 {
2943 wxWindow *child = (wxWindow *)node->Data();
2944 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
2945 {
2946 wxLayoutConstraints *constr = child->GetConstraints();
2947 if (constr)
2948 {
2949 if (succeeded.Member(child))
2950 {
2951 }
2952 else
2953 {
2954 int tempNoChanges = 0;
2955 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
2956 noChanges += tempNoChanges;
2957 if (success)
2958 {
2959 succeeded.Append(child);
2960 }
2961 }
2962 }
2963 }
2964 node = node->Next();
2965 }
2966 noIterations ++;
2967 }
2968 return TRUE;
2969 }
2970
2971 void wxWindow::ResetConstraints()
2972 {
2973 wxLayoutConstraints *constr = GetConstraints();
2974 if (constr)
2975 {
2976 constr->left.SetDone(FALSE);
2977 constr->top.SetDone(FALSE);
2978 constr->right.SetDone(FALSE);
2979 constr->bottom.SetDone(FALSE);
2980 constr->width.SetDone(FALSE);
2981 constr->height.SetDone(FALSE);
2982 constr->centreX.SetDone(FALSE);
2983 constr->centreY.SetDone(FALSE);
2984 }
2985 wxNode *node = m_children.First();
2986 while (node)
2987 {
2988 wxWindow *win = (wxWindow *)node->Data();
2989 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2990 win->ResetConstraints();
2991 node = node->Next();
2992 }
2993 }
2994
2995 // Need to distinguish between setting the 'fake' size for
2996 // windows and sizers, and setting the real values.
2997 void wxWindow::SetConstraintSizes(bool recurse)
2998 {
2999 wxLayoutConstraints *constr = GetConstraints();
3000 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
3001 constr->width.GetDone() && constr->height.GetDone())
3002 {
3003 int x = constr->left.GetValue();
3004 int y = constr->top.GetValue();
3005 int w = constr->width.GetValue();
3006 int h = constr->height.GetValue();
3007
3008 // If we don't want to resize this window, just move it...
3009 if ((constr->width.GetRelationship() != wxAsIs) ||
3010 (constr->height.GetRelationship() != wxAsIs))
3011 {
3012 // Calls Layout() recursively. AAAGH. How can we stop that.
3013 // Simply take Layout() out of non-top level OnSizes.
3014 SizerSetSize(x, y, w, h);
3015 }
3016 else
3017 {
3018 SizerMove(x, y);
3019 }
3020 }
3021 else if (constr)
3022 {
3023 char *windowClass = this->GetClassInfo()->GetClassName();
3024
3025 wxString winName;
3026 if (GetName() == "")
3027 winName = "unnamed";
3028 else
3029 winName = GetName();
3030 wxLogDebug( "Constraint(s) not satisfied for window of type %s, name %s:\n",
3031 (const char *)windowClass,
3032 (const char *)winName);
3033 if (!constr->left.GetDone()) wxLogDebug( " unsatisfied 'left' constraint.\n" );
3034 if (!constr->right.GetDone()) wxLogDebug( " unsatisfied 'right' constraint.\n" );
3035 if (!constr->width.GetDone()) wxLogDebug( " unsatisfied 'width' constraint.\n" );
3036 if (!constr->height.GetDone()) wxLogDebug( " unsatisfied 'height' constraint.\n" );
3037 wxLogDebug( "Please check constraints: try adding AsIs() constraints.\n" );
3038 }
3039
3040 if (recurse)
3041 {
3042 wxNode *node = m_children.First();
3043 while (node)
3044 {
3045 wxWindow *win = (wxWindow *)node->Data();
3046 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3047 win->SetConstraintSizes();
3048 node = node->Next();
3049 }
3050 }
3051 }
3052
3053 // This assumes that all sizers are 'on' the same
3054 // window, i.e. the parent of this window.
3055 void wxWindow::TransformSizerToActual(int *x, int *y) const
3056 {
3057 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
3058 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
3059 return;
3060
3061 int xp, yp;
3062 m_sizerParent->GetPosition(&xp, &yp);
3063 m_sizerParent->TransformSizerToActual(&xp, &yp);
3064 *x += xp;
3065 *y += yp;
3066 }
3067
3068 void wxWindow::SizerSetSize(int x, int y, int w, int h)
3069 {
3070 int xx = x;
3071 int yy = y;
3072 TransformSizerToActual(&xx, &yy);
3073 SetSize(xx, yy, w, h);
3074 }
3075
3076 void wxWindow::SizerMove(int x, int y)
3077 {
3078 int xx = x;
3079 int yy = y;
3080 TransformSizerToActual(&xx, &yy);
3081 Move(xx, yy);
3082 }
3083
3084 // Only set the size/position of the constraint (if any)
3085 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
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 if (w != -1)
3101 {
3102 constr->width.SetValue(w);
3103 constr->width.SetDone(TRUE);
3104 }
3105 if (h != -1)
3106 {
3107 constr->height.SetValue(h);
3108 constr->height.SetDone(TRUE);
3109 }
3110 }
3111 }
3112
3113 void wxWindow::MoveConstraint(int x, int y)
3114 {
3115 wxLayoutConstraints *constr = GetConstraints();
3116 if (constr)
3117 {
3118 if (x != -1)
3119 {
3120 constr->left.SetValue(x);
3121 constr->left.SetDone(TRUE);
3122 }
3123 if (y != -1)
3124 {
3125 constr->top.SetValue(y);
3126 constr->top.SetDone(TRUE);
3127 }
3128 }
3129 }
3130
3131 void wxWindow::GetSizeConstraint(int *w, int *h) const
3132 {
3133 wxLayoutConstraints *constr = GetConstraints();
3134 if (constr)
3135 {
3136 *w = constr->width.GetValue();
3137 *h = constr->height.GetValue();
3138 }
3139 else
3140 GetSize(w, h);
3141 }
3142
3143 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
3144 {
3145 wxLayoutConstraints *constr = GetConstraints();
3146 if (constr)
3147 {
3148 *w = constr->width.GetValue();
3149 *h = constr->height.GetValue();
3150 }
3151 else
3152 GetClientSize(w, h);
3153 }
3154
3155 void wxWindow::GetPositionConstraint(int *x, int *y) const
3156 {
3157 wxLayoutConstraints *constr = GetConstraints();
3158 if (constr)
3159 {
3160 *x = constr->left.GetValue();
3161 *y = constr->top.GetValue();
3162 }
3163 else
3164 GetPosition(x, y);
3165 }
3166
3167 bool wxWindow::AcceptsFocus() const
3168 {
3169 return IsEnabled() && IsShown();
3170 }
3171
3172 void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) )
3173 {
3174 UpdateWindowUI();
3175 }