]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/window.cpp
fixed the install/unix references -Markus
[wxWidgets.git] / src / gtk / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: window.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Created: 01/02/97
6 // Id:
7 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11
12 #ifdef __GNUG__
13 #pragma implementation "window.h"
14 #endif
15
16 #include "wx/defs.h"
17 #include "wx/window.h"
18 #include "wx/dc.h"
19 #include "wx/frame.h"
20 #include "wx/app.h"
21 #include "wx/layout.h"
22 #include "wx/utils.h"
23 #include "wx/dialog.h"
24 #include "wx/msgdlg.h"
25 #include "wx/dcclient.h"
26 #include "wx/dnd.h"
27 #include "wx/mdi.h"
28 #include "wx/menu.h"
29 #include "wx/notebook.h"
30 #include "wx/statusbr.h"
31 #include <wx/intl.h>
32 #include "gdk/gdkkeysyms.h"
33 #include <math.h>
34 #include "wx/gtk/win_gtk.h"
35 #include "gdk/gdkprivate.h"
36
37 //-----------------------------------------------------------------------------
38 // data
39 //-----------------------------------------------------------------------------
40
41 extern wxList wxPendingDelete;
42 extern wxList wxTopLevelWindows;
43 extern bool g_blockEventsOnDrag;
44
45 //-----------------------------------------------------------------------------
46 // "expose_event" (of m_wxwindow, not of m_widget)
47 //-----------------------------------------------------------------------------
48
49 static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
50 {
51 if (!win->HasVMT()) return;
52 if (g_blockEventsOnDrag) return;
53
54 win->m_updateRegion.Union( gdk_event->area.x,
55 gdk_event->area.y,
56 gdk_event->area.width,
57 gdk_event->area.height );
58
59 if (gdk_event->count > 0) return;
60
61 wxPaintEvent event( win->GetId() );
62 event.SetEventObject( win );
63 win->GetEventHandler()->ProcessEvent( event );
64
65 win->m_updateRegion.Clear();
66 }
67
68 //-----------------------------------------------------------------------------
69 // "draw" (of m_wxwindow, not of m_widget)
70 //-----------------------------------------------------------------------------
71
72 static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxWindow *win )
73 {
74 if (!win->HasVMT()) return;
75 if (g_blockEventsOnDrag) return;
76
77 win->m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
78
79 wxPaintEvent event( win->GetId() );
80 event.SetEventObject( win );
81 win->GetEventHandler()->ProcessEvent( event );
82
83 win->m_updateRegion.Clear();
84 }
85
86 //-----------------------------------------------------------------------------
87 // "key_press_event"
88 //-----------------------------------------------------------------------------
89
90 static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
91 {
92 if (!win->HasVMT()) return FALSE;
93 if (g_blockEventsOnDrag) return FALSE;
94
95 /*
96 printf( "OnKeyPress from " );
97 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
98 printf( win->GetClassInfo()->GetClassName() );
99 printf( ".\n" );
100 */
101
102 long key_code = 0;
103 switch (gdk_event->keyval)
104 {
105 case GDK_BackSpace: key_code = WXK_BACK; break;
106 case GDK_Tab: key_code = WXK_TAB; break;
107 case GDK_Linefeed: key_code = WXK_RETURN; break;
108 case GDK_Clear: key_code = WXK_CLEAR; break;
109 case GDK_Return: key_code = WXK_RETURN; break;
110 case GDK_Pause: key_code = WXK_PAUSE; break;
111 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
112 case GDK_Escape: key_code = WXK_ESCAPE; break;
113 case GDK_Delete: key_code = WXK_DELETE; break;
114 case GDK_Home: key_code = WXK_HOME; break;
115 case GDK_Left: key_code = WXK_LEFT; break;
116 case GDK_Up: key_code = WXK_UP; break;
117 case GDK_Right: key_code = WXK_RIGHT; break;
118 case GDK_Down: key_code = WXK_DOWN; break;
119 case GDK_Prior: key_code = WXK_PRIOR; break;
120 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
121 case GDK_Next: key_code = WXK_NEXT; break;
122 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
123 case GDK_End: key_code = WXK_END; break;
124 case GDK_Begin: key_code = WXK_HOME; break;
125 case GDK_Select: key_code = WXK_SELECT; break;
126 case GDK_Print: key_code = WXK_PRINT; break;
127 case GDK_Execute: key_code = WXK_EXECUTE; break;
128 case GDK_Insert: key_code = WXK_INSERT; break;
129 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
130 case GDK_KP_Tab: key_code = WXK_TAB; break;
131 case GDK_KP_Enter: key_code = WXK_RETURN; break;
132 case GDK_KP_Home: key_code = WXK_HOME; break;
133 case GDK_KP_Left: key_code = WXK_LEFT; break;
134 case GDK_KP_Up: key_code = WXK_UP; break;
135 case GDK_KP_Right: key_code = WXK_RIGHT; break;
136 case GDK_KP_Down: key_code = WXK_DOWN; break;
137 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
138 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
139 case GDK_KP_Next: key_code = WXK_NEXT; break;
140 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
141 case GDK_KP_End: key_code = WXK_END; break;
142 case GDK_KP_Begin: key_code = WXK_HOME; break;
143 case GDK_KP_Insert: key_code = WXK_INSERT; break;
144 case GDK_KP_Delete: key_code = WXK_DELETE; break;
145 case GDK_KP_Multiply: key_code = WXK_MULTIPLY; break;
146 case GDK_KP_Add: key_code = WXK_ADD; break;
147 case GDK_KP_Separator: key_code = WXK_SEPARATOR; break;
148 case GDK_KP_Subtract: key_code = WXK_SUBTRACT; break;
149 case GDK_KP_Decimal: key_code = WXK_DECIMAL; break;
150 case GDK_KP_Divide: key_code = WXK_DIVIDE; break;
151 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
152 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
153 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
154 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
155 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
156 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
157 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
158 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
159 case GDK_KP_8: key_code = WXK_NUMPAD7; break;
160 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
161 case GDK_F1: key_code = WXK_F1; break;
162 case GDK_F2: key_code = WXK_F2; break;
163 case GDK_F3: key_code = WXK_F3; break;
164 case GDK_F4: key_code = WXK_F4; break;
165 case GDK_F5: key_code = WXK_F5; break;
166 case GDK_F6: key_code = WXK_F6; break;
167 case GDK_F7: key_code = WXK_F7; break;
168 case GDK_F8: key_code = WXK_F8; break;
169 case GDK_F9: key_code = WXK_F9; break;
170 case GDK_F10: key_code = WXK_F10; break;
171 case GDK_F11: key_code = WXK_F11; break;
172 case GDK_F12: key_code = WXK_F12; break;
173 default:
174 {
175 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
176 key_code = gdk_event->keyval;
177 }
178 }
179
180 if (!key_code) return FALSE;
181
182 wxKeyEvent event( wxEVT_CHAR );
183 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
184 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
185 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
186 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
187 event.m_keyCode = key_code;
188 event.m_x = 0;
189 event.m_y = 0;
190 event.SetEventObject( win );
191
192 bool ret = win->GetEventHandler()->ProcessEvent( event );
193
194 if (!ret)
195 {
196 int command = win->GetAcceleratorTable()->GetCommand( event );
197 if (command != -1)
198 {
199 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
200 ret = win->GetEventHandler()->ProcessEvent( command_event );
201 }
202 }
203
204 if (ret)
205 {
206 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
207 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
208 }
209
210 return ret;
211 }
212
213 //-----------------------------------------------------------------------------
214 // "button_press_event"
215 //-----------------------------------------------------------------------------
216
217 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
218 {
219 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
220
221 if (g_blockEventsOnDrag) return TRUE;
222
223 if (win->m_wxwindow)
224 {
225 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
226 {
227 gtk_widget_grab_focus (win->m_wxwindow);
228
229 /*
230 printf( "GrabFocus from " );
231 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
232 printf( win->GetClassInfo()->GetClassName() );
233 printf( ".\n" );
234 */
235
236 }
237 }
238
239 if (!win->HasVMT()) return TRUE;
240
241 /*
242 printf( "OnButtonPress from " );
243 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
244 printf( win->GetClassInfo()->GetClassName() );
245 printf( ".\n" );
246 */
247
248 wxEventType event_type = wxEVT_LEFT_DOWN;
249
250 if (gdk_event->button == 1)
251 {
252 switch (gdk_event->type)
253 {
254 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
255 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
256 default: break;
257 }
258 }
259 else if (gdk_event->button == 2)
260 {
261 switch (gdk_event->type)
262 {
263 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
264 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
265 default: break;
266 }
267 }
268 else if (gdk_event->button == 3)
269 {
270 switch (gdk_event->type)
271 {
272 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
273 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
274 default: break;
275 }
276 }
277
278 wxMouseEvent event( event_type );
279 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
280 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
281 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
282 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
283 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
284 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
285 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
286
287 event.m_x = (long)gdk_event->x;
288 event.m_y = (long)gdk_event->y;
289
290 // Some control don't have their own X window and thus cannot get
291 // any events.
292
293 wxNode *node = win->GetChildren()->First();
294 while (node)
295 {
296 wxWindow *child = (wxWindow*)node->Data();
297 if ((child->m_x <= event.m_x) &&
298 (child->m_y <= event.m_y) &&
299 (child->m_x+child->m_width >= event.m_x) &&
300 (child->m_y+child->m_height >= event.m_y))
301 {
302 win = child;
303 event.m_x -= child->m_x;
304 event.m_y -= child->m_y;
305 break;
306 }
307 node = node->Next();
308 }
309
310 event.SetEventObject( win );
311
312 if (win->GetEventHandler()->ProcessEvent( event ))
313 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
314
315 return TRUE;
316 }
317
318 //-----------------------------------------------------------------------------
319 // "button_release"
320 //-----------------------------------------------------------------------------
321
322 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
323 {
324 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
325 if (g_blockEventsOnDrag) return TRUE;
326
327 if (!win->HasVMT()) return TRUE;
328
329 /*
330 printf( "OnButtonRelease from " );
331 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
332 printf( win->GetClassInfo()->GetClassName() );
333 printf( ".\n" );
334 */
335
336 wxEventType event_type = wxEVT_NULL;
337
338 switch (gdk_event->button)
339 {
340 case 1: event_type = wxEVT_LEFT_UP; break;
341 case 2: event_type = wxEVT_MIDDLE_UP; break;
342 case 3: event_type = wxEVT_RIGHT_UP; break;
343 }
344
345 wxMouseEvent event( event_type );
346 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
347 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
348 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
349 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
350 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
351 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
352 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
353 event.m_x = (long)gdk_event->x;
354 event.m_y = (long)gdk_event->y;
355
356 // Some control don't have their own X window and thus cannot get
357 // any events.
358
359 wxNode *node = win->GetChildren()->First();
360 while (node)
361 {
362 wxWindow *child = (wxWindow*)node->Data();
363 if ((child->m_x <= event.m_x) &&
364 (child->m_y <= event.m_y) &&
365 (child->m_x+child->m_width >= event.m_x) &&
366 (child->m_y+child->m_height >= event.m_y))
367 {
368 win = child;
369 event.m_x -= child->m_x;
370 event.m_y -= child->m_y;
371 break;
372 }
373 node = node->Next();
374 }
375
376 event.SetEventObject( win );
377
378 if (win->GetEventHandler()->ProcessEvent( event ))
379 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
380
381 return TRUE;
382 }
383
384 //-----------------------------------------------------------------------------
385 // "motion_notify_event"
386 //-----------------------------------------------------------------------------
387
388 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
389 {
390 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
391 if (g_blockEventsOnDrag) return TRUE;
392
393 if (!win->HasVMT()) return TRUE;
394
395 /*
396 printf( "OnMotion from " );
397 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
398 printf( win->GetClassInfo()->GetClassName() );
399 printf( ".\n" );
400 */
401
402 wxMouseEvent event( wxEVT_MOTION );
403 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
404 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
405 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
406 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
407 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
408 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
409 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
410
411 event.m_x = (long)gdk_event->x;
412 event.m_y = (long)gdk_event->y;
413
414 // Some control don't have their own X window and thus cannot get
415 // any events.
416
417 wxNode *node = win->GetChildren()->First();
418 while (node)
419 {
420 wxWindow *child = (wxWindow*)node->Data();
421 if ((child->m_x <= event.m_x) &&
422 (child->m_y <= event.m_y) &&
423 (child->m_x+child->m_width >= event.m_x) &&
424 (child->m_y+child->m_height >= event.m_y))
425 {
426 win = child;
427 event.m_x -= child->m_x;
428 event.m_y -= child->m_y;
429 break;
430 }
431 node = node->Next();
432 }
433
434 event.SetEventObject( win );
435
436 if (win->GetEventHandler()->ProcessEvent( event ))
437 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
438
439 return TRUE;
440 }
441
442 //-----------------------------------------------------------------------------
443 // "focus_in_event"
444 //-----------------------------------------------------------------------------
445
446 static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
447 {
448 if (g_blockEventsOnDrag) return TRUE;
449 if (win->m_wxwindow)
450 {
451 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
452 {
453 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
454 /*
455 printf( "SetFocus flag from " );
456 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
457 printf( win->GetClassInfo()->GetClassName() );
458 printf( ".\n" );
459 */
460 }
461 }
462
463 if (!win->HasVMT()) return TRUE;
464
465 /*
466 printf( "OnSetFocus from " );
467 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
468 printf( win->GetClassInfo()->GetClassName() );
469 printf( " " );
470 printf( WXSTRINGCAST win->GetLabel() );
471 printf( ".\n" );
472 */
473
474 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
475 event.SetEventObject( win );
476
477 if (win->GetEventHandler()->ProcessEvent( event ))
478 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
479
480 return TRUE;
481 }
482
483 //-----------------------------------------------------------------------------
484 // "focus_out_event"
485 //-----------------------------------------------------------------------------
486
487 static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
488 {
489 if (g_blockEventsOnDrag) return TRUE;
490 if (win->m_wxwindow)
491 {
492 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
493 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
494 }
495
496 if (!win->HasVMT()) return TRUE;
497
498 /*
499 printf( "OnKillFocus from " );
500 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
501 printf( win->GetClassInfo()->GetClassName() );
502 printf( ".\n" );
503 */
504
505 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
506 event.SetEventObject( win );
507
508 if (win->GetEventHandler()->ProcessEvent( event ))
509 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
510
511 return TRUE;
512 }
513
514 //-----------------------------------------------------------------------------
515 // "value_changed" from m_vAdjust
516 //-----------------------------------------------------------------------------
517
518 static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
519 {
520 if (g_blockEventsOnDrag) return;
521
522 /*
523 printf( "OnVScroll from " );
524 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
525 printf( win->GetClassInfo()->GetClassName() );
526 printf( ".\n" );
527 */
528
529 if (!win->HasVMT()) return;
530
531 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
532 if (fabs(diff) < 0.2) return;
533
534 wxEventType command = wxEVT_NULL;
535
536 float line_step = win->m_vAdjust->step_increment;
537 float page_step = win->m_vAdjust->page_increment;
538
539 if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
540 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
541 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
542 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
543 else command = wxEVT_SCROLL_THUMBTRACK;
544
545 int value = (int)(win->m_vAdjust->value+0.5);
546
547 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
548 event.SetEventObject( win );
549 win->GetEventHandler()->ProcessEvent( event );
550 }
551
552 //-----------------------------------------------------------------------------
553 // "value_changed" from m_hAdjust
554 //-----------------------------------------------------------------------------
555
556 static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
557 {
558 if (g_blockEventsOnDrag) return;
559
560 /*
561 printf( "OnHScroll from " );
562 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
563 printf( win->GetClassInfo()->GetClassName() );
564 printf( ".\n" );
565 */
566
567 if (!win->HasVMT()) return;
568
569 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
570 if (fabs(diff) < 0.2) return;
571
572 wxEventType command = wxEVT_NULL;
573
574 float line_step = win->m_hAdjust->step_increment;
575 float page_step = win->m_hAdjust->page_increment;
576
577 if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
578 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
579 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
580 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
581 else command = wxEVT_SCROLL_THUMBTRACK;
582
583 int value = (int)(win->m_hAdjust->value+0.5);
584
585 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
586 event.SetEventObject( win );
587 win->GetEventHandler()->ProcessEvent( event );
588 }
589
590 //-----------------------------------------------------------------------------
591 // "changed" from m_vAdjust
592 //-----------------------------------------------------------------------------
593
594 static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
595 {
596 if (g_blockEventsOnDrag) return;
597
598 /*
599 printf( "OnVScroll change from " );
600 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
601 printf( win->GetClassInfo()->GetClassName() );
602 printf( ".\n" );
603 */
604
605 if (!win->HasVMT()) return;
606
607 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
608 int value = (int)(win->m_vAdjust->value+0.5);
609
610 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
611 event.SetEventObject( win );
612 win->GetEventHandler()->ProcessEvent( event );
613 }
614
615 //-----------------------------------------------------------------------------
616 // "changed" from m_hAdjust
617 //-----------------------------------------------------------------------------
618
619 static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
620 {
621 if (g_blockEventsOnDrag) return;
622
623 /*
624 printf( "OnHScroll change from " );
625 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
626 printf( win->GetClassInfo()->GetClassName() );
627 printf( ".\n" );
628 */
629
630 if (!win->HasVMT()) return;
631
632 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
633 int value = (int)(win->m_hAdjust->value+0.5);
634
635 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
636 event.SetEventObject( win );
637 win->GetEventHandler()->ProcessEvent( event );
638 }
639
640 //-----------------------------------------------------------------------------
641 // "drop_data_available_event"
642 //-----------------------------------------------------------------------------
643
644 static void gtk_window_drop_callback( GtkWidget *widget, GdkEvent *event, wxWindow *win )
645 {
646 if (!win->HasVMT()) return;
647
648 if (win->GetDropTarget())
649 {
650 int x = 0;
651 int y = 0;
652 gdk_window_get_pointer( widget->window, &x, &y, (GdkModifierType *) NULL );
653 win->GetDropTarget()->Drop( event, x, y );
654 }
655
656 /*
657 g_free (event->dropdataavailable.data);
658 g_free (event->dropdataavailable.data_type);
659 */
660 }
661
662 //-----------------------------------------------------------------------------
663 // "enter_notify_event"
664 //-----------------------------------------------------------------------------
665
666 static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
667 {
668 if (widget->window != gdk_event->window) return TRUE;
669 if (g_blockEventsOnDrag) return TRUE;
670 if (!win->HasVMT()) return TRUE;
671
672 if (widget->window)
673 gdk_window_set_cursor( widget->window, win->m_cursor->GetCursor() );
674
675 wxMouseEvent event( wxEVT_ENTER_WINDOW );
676 event.SetEventObject( win );
677 return win->GetEventHandler()->ProcessEvent( event );
678 }
679
680 //-----------------------------------------------------------------------------
681 // "leave_notify_event"
682 //-----------------------------------------------------------------------------
683
684 static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
685 {
686 if (widget->window != gdk_event->window) return TRUE;
687 if (!win->HasVMT()) return TRUE;
688 if (g_blockEventsOnDrag) return TRUE;
689
690 if (widget->window)
691 gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
692
693 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
694 event.SetEventObject( win );
695 return win->GetEventHandler()->ProcessEvent( event );
696 }
697
698 //-----------------------------------------------------------------------------
699 // wxWindow
700 //-----------------------------------------------------------------------------
701
702 IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler)
703
704 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
705 EVT_SIZE(wxWindow::OnSize)
706 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
707 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
708 EVT_IDLE(wxWindow::OnIdle)
709 END_EVENT_TABLE()
710
711 wxWindow::wxWindow()
712 {
713 m_widget = (GtkWidget *) NULL;
714 m_wxwindow = (GtkWidget *) NULL;
715 m_parent = (wxWindow *) NULL;
716 m_children.DeleteContents( FALSE );
717 m_x = 0;
718 m_y = 0;
719 m_width = 0;
720 m_height = 0;
721 m_minWidth = -1;
722 m_minHeight = -1;
723 m_maxWidth = -1;
724 m_maxHeight = -1;
725 m_retCode = 0;
726 m_eventHandler = this;
727 m_windowValidator = (wxValidator *) NULL;
728 m_windowId = -1;
729 m_cursor = new wxCursor( wxCURSOR_ARROW );
730 m_font = *wxSWISS_FONT;
731 m_windowStyle = 0;
732 m_windowName = "noname";
733 m_constraints = (wxLayoutConstraints *) NULL;
734 m_constraintsInvolvedIn = (wxList *) NULL;
735 m_windowSizer = (wxSizer *) NULL;
736 m_sizerParent = (wxWindow *) NULL;
737 m_autoLayout = FALSE;
738 m_sizeSet = FALSE;
739 m_hasVMT = FALSE;
740 m_needParent = TRUE;
741 m_hasScrolling = FALSE;
742 m_hAdjust = (GtkAdjustment *) NULL;
743 m_vAdjust = (GtkAdjustment *) NULL;
744 m_oldHorizontalPos = 0.0;
745 m_oldVerticalPos = 0.0;
746 m_isShown = FALSE;
747 m_isEnabled = TRUE;
748 m_pDropTarget = (wxDropTarget *) NULL;
749 m_resizing = FALSE;
750 }
751
752 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
753 const wxPoint &pos, const wxSize &size,
754 long style, const wxString &name )
755 {
756 m_isShown = FALSE;
757 m_isEnabled = TRUE;
758 m_needParent = TRUE;
759
760 m_cursor = (wxCursor *) NULL;
761
762 PreCreation( parent, id, pos, size, style, name );
763
764 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
765 m_hasScrolling = TRUE;
766
767 GtkScrolledWindow *s_window;
768 s_window = GTK_SCROLLED_WINDOW(m_widget);
769
770 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
771 scroll_class->scrollbar_spacing = 0;
772
773 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
774
775 m_oldHorizontalPos = 0.0;
776 m_oldVerticalPos = 0.0;
777
778 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
779 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
780
781 gtk_signal_connect (GTK_OBJECT (m_hAdjust), "value_changed",
782 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
783 gtk_signal_connect (GTK_OBJECT (m_vAdjust), "value_changed",
784 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
785
786 gtk_signal_connect (GTK_OBJECT (m_hAdjust), "changed",
787 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
788 gtk_signal_connect (GTK_OBJECT (m_vAdjust), "changed",
789 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
790
791 GtkViewport *viewport;
792 viewport = GTK_VIEWPORT(s_window->viewport);
793
794 if (m_windowStyle & wxRAISED_BORDER)
795 {
796 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
797 }
798 else if (m_windowStyle & wxSUNKEN_BORDER)
799 {
800 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
801 }
802 else
803 {
804 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
805 }
806
807 m_wxwindow = gtk_myfixed_new();
808
809 if (m_wxwindow) GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
810
811 if (m_windowStyle & wxTAB_TRAVERSAL == wxTAB_TRAVERSAL)
812 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
813 else
814 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
815
816 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
817
818 // shut the viewport up
819 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
820 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
821
822 // I _really_ don't want scrollbars in the beginning
823 m_vAdjust->lower = 0.0;
824 m_vAdjust->upper = 1.0;
825 m_vAdjust->value = 0.0;
826 m_vAdjust->step_increment = 1.0;
827 m_vAdjust->page_increment = 1.0;
828 m_vAdjust->page_size = 5.0;
829 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
830 m_hAdjust->lower = 0.0;
831 m_hAdjust->upper = 1.0;
832 m_hAdjust->value = 0.0;
833 m_hAdjust->step_increment = 1.0;
834 m_hAdjust->page_increment = 1.0;
835 m_hAdjust->page_size = 5.0;
836 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
837
838 gtk_widget_show( m_wxwindow );
839
840 PostCreation();
841
842 Show( TRUE );
843
844 return TRUE;
845 }
846
847 wxWindow::~wxWindow(void)
848 {
849 m_hasVMT = FALSE;
850
851 if (m_pDropTarget) delete m_pDropTarget;
852
853 if (m_parent) m_parent->RemoveChild( this );
854 if (m_widget) Show( FALSE );
855
856 DestroyChildren();
857
858 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
859
860 if (m_widget) gtk_widget_destroy( m_widget );
861
862 wxDELETE(m_cursor);
863
864 DeleteRelatedConstraints();
865 if (m_constraints)
866 {
867 // This removes any dangling pointers to this window
868 // in other windows' constraintsInvolvedIn lists.
869 UnsetConstraints(m_constraints);
870 delete m_constraints;
871 m_constraints = (wxLayoutConstraints *) NULL;
872 }
873 if (m_windowSizer)
874 {
875 delete m_windowSizer;
876 m_windowSizer = (wxSizer *) NULL;
877 }
878 // If this is a child of a sizer, remove self from parent
879 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
880
881 // Just in case the window has been Closed, but
882 // we're then deleting immediately: don't leave
883 // dangling pointers.
884 wxPendingDelete.DeleteObject(this);
885
886 // Just in case we've loaded a top-level window via
887 // wxWindow::LoadNativeDialog but we weren't a dialog
888 // class
889 wxTopLevelWindows.DeleteObject(this);
890
891 if (m_windowValidator) delete m_windowValidator;
892 }
893
894 void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
895 const wxPoint &pos, const wxSize &size,
896 long style, const wxString &name )
897 {
898 if (m_needParent && (parent == NULL))
899 wxFatalError( "Need complete parent.", name );
900
901 m_widget = (GtkWidget *) NULL;
902 m_hasVMT = FALSE;
903 m_parent = parent;
904 m_children.DeleteContents( FALSE );
905 m_x = (int)pos.x;
906 m_y = (int)pos.y;
907 m_width = size.x;
908 if (m_width == -1) m_width = 20;
909 m_height = size.y;
910 if (m_height == -1) m_height = 20;
911 m_minWidth = -1;
912 m_minHeight = -1;
913 m_maxWidth = -1;
914 m_maxHeight = -1;
915 m_retCode = 0;
916 m_eventHandler = this;
917 m_windowId = id;
918 m_sizeSet = FALSE;
919 if (m_cursor == NULL)
920 m_cursor = new wxCursor( wxCURSOR_ARROW );
921 m_font = *wxSWISS_FONT;
922 m_backgroundColour = wxWHITE;
923 m_foregroundColour = wxBLACK;
924 m_windowStyle = style;
925 m_windowName = name;
926 m_constraints = (wxLayoutConstraints *) NULL;
927 m_constraintsInvolvedIn = (wxList *) NULL;
928 m_windowSizer = (wxSizer *) NULL;
929 m_sizerParent = (wxWindow *) NULL;
930 m_autoLayout = FALSE;
931 m_pDropTarget = (wxDropTarget *) NULL;
932 m_resizing = FALSE;
933 m_windowValidator = (wxValidator *) NULL;
934 }
935
936 void wxWindow::PostCreation(void)
937 {
938 if (m_parent) m_parent->AddChild( this );
939
940 // GtkStyle *style = m_widget->style;
941 // style->font = m_font.GetInternalFont( 1.0 ); // destroy old font ?
942
943 GtkWidget *connect_widget = GetConnectWidget();
944
945 if (m_wxwindow)
946 {
947 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
948 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
949
950 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
951 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
952 }
953
954 gtk_signal_connect( GTK_OBJECT(connect_widget), "key_press_event",
955 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
956
957 gtk_signal_connect( GTK_OBJECT(connect_widget), "button_press_event",
958 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
959
960 gtk_signal_connect( GTK_OBJECT(connect_widget), "button_release_event",
961 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
962
963 gtk_signal_connect( GTK_OBJECT(connect_widget), "motion_notify_event",
964 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
965
966 gtk_signal_connect( GTK_OBJECT(connect_widget), "focus_in_event",
967 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
968
969 gtk_signal_connect( GTK_OBJECT(connect_widget), "focus_out_event",
970 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
971
972 // Only for cursor handling
973
974 gtk_signal_connect( GTK_OBJECT(m_widget), "enter_notify_event",
975 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
976
977 gtk_signal_connect( GTK_OBJECT(m_widget), "leave_notify_event",
978 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
979
980 if (m_wxwindow)
981 {
982 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "enter_notify_event",
983 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
984
985 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "leave_notify_event",
986 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
987 }
988
989 if (m_widget && m_parent) gtk_widget_realize( m_widget );
990
991 if (m_wxwindow)
992 {
993 gtk_widget_realize( m_wxwindow );
994 gdk_gc_set_exposures( m_wxwindow->style->fg_gc[0], TRUE );
995 }
996
997 SetCursor( wxSTANDARD_CURSOR );
998
999 m_hasVMT = TRUE;
1000 }
1001
1002 bool wxWindow::HasVMT(void)
1003 {
1004 return m_hasVMT;
1005 }
1006
1007 bool wxWindow::Close( bool force )
1008 {
1009 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1010 event.SetEventObject(this);
1011 event.SetForce(force);
1012
1013 return GetEventHandler()->ProcessEvent(event);
1014 }
1015
1016 bool wxWindow::Destroy(void)
1017 {
1018 m_hasVMT = FALSE;
1019 delete this;
1020 return TRUE;
1021 }
1022
1023 bool wxWindow::DestroyChildren(void)
1024 {
1025 if (GetChildren())
1026 {
1027 wxNode *node;
1028 while ((node = GetChildren()->First()) != (wxNode *)NULL)
1029 {
1030 wxWindow *child;
1031 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
1032 {
1033 delete child;
1034 if (GetChildren()->Member(child)) delete node;
1035 }
1036 }
1037 }
1038 return TRUE;
1039 }
1040
1041 void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1042 {
1043 // are we to set fonts here ?
1044 }
1045
1046 void wxWindow::ImplementSetSize(void)
1047 {
1048 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1049 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
1050 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_minWidth;
1051 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_minHeight;
1052 gtk_widget_set_usize( m_widget, m_width, m_height );
1053 }
1054
1055 void wxWindow::ImplementSetPosition(void)
1056 {
1057 if (IS_KIND_OF(this,wxFrame) || IS_KIND_OF(this,wxDialog))
1058 {
1059 if ((m_x != -1) || (m_y != -1))
1060 gtk_widget_set_uposition( m_widget, m_x, m_y );
1061 return;
1062 }
1063
1064 if (!m_parent)
1065 {
1066 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1067 return;
1068 }
1069
1070 if ((m_parent) && (m_parent->m_wxwindow))
1071 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x, m_y );
1072
1073 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1074 }
1075
1076 void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
1077 {
1078 if (m_resizing) return; // I don't like recursions
1079 m_resizing = TRUE;
1080
1081 int newX = x;
1082 int newY = y;
1083 int newW = width;
1084 int newH = height;
1085
1086 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1087 {
1088 if (newX == -1) newX = m_x;
1089 if (newY == -1) newY = m_y;
1090 if (newW == -1) newW = m_width;
1091 if (newH == -1) newH = m_height;
1092 }
1093
1094 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1095 {
1096 if (newW == -1) newW = 80;
1097 }
1098
1099 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1100 {
1101 if (newH == -1) newH = 26;
1102 }
1103
1104 if ((m_x != newX) || (m_y != newY) || (!m_sizeSet))
1105 {
1106 m_x = newX;
1107 m_y = newY;
1108 ImplementSetPosition();
1109 }
1110 if ((m_width != newW) || (m_height != newH) || (!m_sizeSet))
1111 {
1112 m_width = newW;
1113 m_height = newH;
1114 ImplementSetSize();
1115 }
1116 m_sizeSet = TRUE;
1117
1118 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1119 event.SetEventObject( this );
1120 ProcessEvent( event );
1121
1122 m_resizing = FALSE;
1123 }
1124
1125 void wxWindow::SetSize( int width, int height )
1126 {
1127 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
1128 }
1129
1130 void wxWindow::Move( int x, int y )
1131 {
1132 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
1133 }
1134
1135 void wxWindow::GetSize( int *width, int *height ) const
1136 {
1137 if (width) (*width) = m_width;
1138 if (height) (*height) = m_height;
1139 }
1140
1141 void wxWindow::SetClientSize( int width, int height )
1142 {
1143 if (!m_wxwindow)
1144 {
1145 SetSize( width, height );
1146 }
1147 else
1148 {
1149 int dw = 0;
1150 int dh = 0;
1151
1152 if (!m_hasScrolling)
1153 {
1154 /*
1155 do we have sunken dialogs ?
1156
1157 GtkStyleClass *window_class = m_wxwindow->style->klass;
1158
1159 dw += 2 * window_class->xthickness;
1160 dh += 2 * window_class->ythickness;
1161 */
1162 }
1163 else
1164 {
1165 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1166 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1167
1168 GtkWidget *viewport = scroll_window->viewport;
1169 GtkStyleClass *viewport_class = viewport->style->klass;
1170
1171 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1172 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1173
1174 if ((m_windowStyle & wxRAISED_BORDER) ||
1175 (m_windowStyle & wxSUNKEN_BORDER))
1176 {
1177 dw += 2 * viewport_class->xthickness;
1178 dh += 2 * viewport_class->ythickness;
1179 }
1180
1181 if (GTK_WIDGET_VISIBLE(vscrollbar))
1182 {
1183 dw += vscrollbar->allocation.width;
1184 dw += scroll_class->scrollbar_spacing;
1185 }
1186
1187 if (GTK_WIDGET_VISIBLE(hscrollbar))
1188 {
1189 dh += hscrollbar->allocation.height;
1190 dw += scroll_class->scrollbar_spacing;
1191 }
1192 }
1193
1194 SetSize( width+dw, height+dh );
1195 }
1196 }
1197
1198 void wxWindow::GetClientSize( int *width, int *height ) const
1199 {
1200 if (!m_wxwindow)
1201 {
1202 if (width) (*width) = m_width;
1203 if (height) (*height) = m_height;
1204 }
1205 else
1206 {
1207 int dw = 0;
1208 int dh = 0;
1209
1210 if (!m_hasScrolling)
1211 {
1212 /*
1213 do we have sunken dialogs ?
1214
1215 GtkStyleClass *window_class = m_wxwindow->style->klass;
1216
1217 dw += 2 * window_class->xthickness;
1218 dh += 2 * window_class->ythickness;
1219 */
1220 }
1221 else
1222 {
1223 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1224 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1225
1226 GtkWidget *viewport = scroll_window->viewport;
1227 GtkStyleClass *viewport_class = viewport->style->klass;
1228
1229 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1230 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1231
1232 if ((m_windowStyle & wxRAISED_BORDER) ||
1233 (m_windowStyle & wxSUNKEN_BORDER))
1234 {
1235 dw += 2 * viewport_class->xthickness;
1236 dh += 2 * viewport_class->ythickness;
1237 }
1238
1239 if (GTK_WIDGET_VISIBLE(vscrollbar))
1240 {
1241 // dw += vscrollbar->allocation.width;
1242 dw += 15; // range.slider_width = 11 + 2*2pts edge
1243 dw += scroll_class->scrollbar_spacing;
1244 }
1245
1246 if (GTK_WIDGET_VISIBLE(hscrollbar))
1247 {
1248 // dh += hscrollbar->allocation.height;
1249 dh += 15;
1250 dh += scroll_class->scrollbar_spacing;
1251 }
1252 }
1253
1254 if (width) (*width) = m_width - dw;
1255 if (height) (*height) = m_height - dh;
1256 }
1257 }
1258
1259 void wxWindow::GetPosition( int *x, int *y ) const
1260 {
1261 if (x) (*x) = m_x;
1262 if (y) (*y) = m_y;
1263 }
1264
1265 void wxWindow::ClientToScreen( int *x, int *y )
1266 {
1267 GdkWindow *source = (GdkWindow *) NULL;
1268 if (m_wxwindow)
1269 source = m_wxwindow->window;
1270 else
1271 source = m_widget->window;
1272
1273 int org_x = 0;
1274 int org_y = 0;
1275 gdk_window_get_origin( source, &org_x, &org_y );
1276
1277 if (!m_wxwindow)
1278 {
1279 if (GTK_WIDGET_NO_WINDOW (m_widget))
1280 {
1281 org_x += m_widget->allocation.x;
1282 org_y += m_widget->allocation.y;
1283 }
1284 }
1285
1286 if (x) *x += org_x;
1287 if (y) *y += org_y;
1288 }
1289
1290 void wxWindow::ScreenToClient( int *x, int *y )
1291 {
1292 GdkWindow *source = (GdkWindow *) NULL;
1293 if (m_wxwindow)
1294 source = m_wxwindow->window;
1295 else
1296 source = m_widget->window;
1297
1298 int org_x = 0;
1299 int org_y = 0;
1300 gdk_window_get_origin( source, &org_x, &org_y );
1301
1302 if (!m_wxwindow)
1303 {
1304 if (GTK_WIDGET_NO_WINDOW (m_widget))
1305 {
1306 org_x += m_widget->allocation.x;
1307 org_y += m_widget->allocation.y;
1308 }
1309 }
1310
1311 if (x) *x -= org_x;
1312 if (y) *y -= org_y;
1313 }
1314
1315 void wxWindow::Centre( int direction )
1316 {
1317 if (IS_KIND_OF(this,wxDialog) || IS_KIND_OF(this,wxFrame))
1318 {
1319 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (gdk_screen_width () - m_width) / 2;
1320 if (direction & wxVERTICAL == wxVERTICAL) m_y = (gdk_screen_height () - m_height) / 2;
1321 ImplementSetPosition();
1322 }
1323 else
1324 {
1325 if (m_parent)
1326 {
1327 int p_w = 0;
1328 int p_h = 0;
1329 m_parent->GetSize( &p_w, &p_h );
1330 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (p_w - m_width) / 2;
1331 if (direction & wxVERTICAL == wxVERTICAL) m_y = (p_h - m_height) / 2;
1332 ImplementSetPosition();
1333 }
1334 }
1335 }
1336
1337 void wxWindow::Fit(void)
1338 {
1339 int maxX = 0;
1340 int maxY = 0;
1341 wxNode *node = GetChildren()->First();
1342 while ( node )
1343 {
1344 wxWindow *win = (wxWindow *)node->Data();
1345 int wx, wy, ww, wh;
1346 win->GetPosition(&wx, &wy);
1347 win->GetSize(&ww, &wh);
1348 if ( wx + ww > maxX )
1349 maxX = wx + ww;
1350 if ( wy + wh > maxY )
1351 maxY = wy + wh;
1352
1353 node = node->Next();
1354 }
1355 SetClientSize(maxX + 5, maxY + 10);
1356 }
1357
1358 void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
1359 {
1360 m_minWidth = minW;
1361 m_minHeight = minH;
1362 m_maxWidth = maxW;
1363 m_maxHeight = maxH;
1364 }
1365
1366 void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
1367 {
1368 //if (GetAutoLayout()) Layout();
1369 }
1370
1371 bool wxWindow::Show( bool show )
1372 {
1373 if (show)
1374 gtk_widget_show( m_widget );
1375 else
1376 gtk_widget_hide( m_widget );
1377 m_isShown = show;
1378 return TRUE;
1379 }
1380
1381 void wxWindow::Enable( bool enable )
1382 {
1383 m_isEnabled = enable;
1384 gtk_widget_set_sensitive( m_widget, enable );
1385 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
1386 }
1387
1388 int wxWindow::GetCharHeight(void) const
1389 {
1390 GdkFont *font = m_font.GetInternalFont( 1.0 );
1391 return font->ascent + font->descent;
1392 }
1393
1394 int wxWindow::GetCharWidth(void) const
1395 {
1396 GdkFont *font = m_font.GetInternalFont( 1.0 );
1397 return gdk_string_width( font, "H" );
1398 }
1399
1400 void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
1401 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
1402 {
1403 wxFont fontToUse = m_font;
1404 if (theFont) fontToUse = *theFont;
1405
1406 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
1407 if (x) (*y) = gdk_string_width( font, string );
1408 if (y) (*y) = font->ascent + font->descent;
1409 if (descent) (*descent) = font->descent;
1410 if (externalLeading) (*externalLeading) = 0; // ??
1411 }
1412
1413 void wxWindow::MakeModal( bool modal )
1414 {
1415 return;
1416 // Disable all other windows
1417 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
1418 {
1419 wxNode *node = wxTopLevelWindows.First();
1420 while (node)
1421 {
1422 wxWindow *win = (wxWindow *)node->Data();
1423 if (win != this)
1424 win->Enable(!modal);
1425
1426 node = node->Next();
1427 }
1428 }
1429 }
1430
1431 void wxWindow::SetFocus(void)
1432 {
1433 GtkWidget *connect_widget = GetConnectWidget();
1434 if (connect_widget)
1435 {
1436 if (GTK_WIDGET_CAN_FOCUS(connect_widget) && !GTK_WIDGET_HAS_FOCUS (connect_widget) )
1437 {
1438 gtk_widget_grab_focus (connect_widget);
1439 }
1440 }
1441 }
1442
1443 bool wxWindow::OnClose(void)
1444 {
1445 return TRUE;
1446 }
1447
1448 void wxWindow::AddChild( wxWindow *child )
1449 {
1450 // Addchild is (often) called before the program
1451 // has left the parents constructor so that no
1452 // virtual tables work yet. The approach below
1453 // practically imitates virtual tables, i.e. it
1454 // implements a different AddChild() behaviour
1455 // for wxFrame, wxDialog, wxWindow and
1456 // wxMDIParentFrame.
1457
1458 // wxFrame and wxDialog as children aren't placed into the parents
1459
1460 if (( IS_KIND_OF(child,wxFrame) || IS_KIND_OF(child,wxDialog) ) &&
1461 (!IS_KIND_OF(child,wxMDIChildFrame)))
1462 {
1463 m_children.Append( child );
1464
1465 if ((child->m_x != -1) && (child->m_y != -1))
1466 gtk_widget_set_uposition( child->m_widget, child->m_x, child->m_y );
1467
1468 return;
1469 }
1470
1471 // In the case of an wxMDIChildFrame descendant, we use the
1472 // client windows's AddChild()
1473
1474 if (IS_KIND_OF(this,wxMDIParentFrame))
1475 {
1476 if (IS_KIND_OF(child,wxMDIChildFrame))
1477 {
1478 wxMDIClientWindow *client = ((wxMDIParentFrame*)this)->GetClientWindow();
1479 if (client)
1480 {
1481 client->AddChild( child );
1482 return;
1483 }
1484 }
1485 }
1486
1487 // wxNotebook is very special, so it has a private AddChild()
1488
1489 if (IS_KIND_OF(this,wxNotebook))
1490 {
1491 wxNotebook *tab = (wxNotebook*)this;
1492 tab->AddChild( child );
1493 return;
1494 }
1495
1496 // wxFrame has a private AddChild
1497
1498 if (IS_KIND_OF(this,wxFrame) && !IS_KIND_OF(this,wxMDIChildFrame))
1499 {
1500 wxFrame *frame = (wxFrame*)this;
1501 frame->AddChild( child );
1502 return;
1503 }
1504
1505 // All the rest
1506
1507 m_children.Append( child );
1508 if (m_wxwindow) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow), child->m_widget,
1509 child->m_x, child->m_y );
1510
1511 gtk_widget_set_usize( child->m_widget, child->m_width, child->m_height );
1512 }
1513
1514 wxList *wxWindow::GetChildren(void)
1515 {
1516 return (&m_children);
1517 }
1518
1519 void wxWindow::RemoveChild( wxWindow *child )
1520 {
1521 if (GetChildren())
1522 GetChildren()->DeleteObject( child );
1523 child->m_parent = (wxWindow *) NULL;
1524 }
1525
1526 void wxWindow::SetReturnCode( int retCode )
1527 {
1528 m_retCode = retCode;
1529 }
1530
1531 int wxWindow::GetReturnCode(void)
1532 {
1533 return m_retCode;
1534 }
1535
1536 void wxWindow::Raise(void)
1537 {
1538 if (m_widget) gdk_window_raise( m_widget->window );
1539 }
1540
1541 void wxWindow::Lower(void)
1542 {
1543 if (m_widget) gdk_window_lower( m_widget->window );
1544 }
1545
1546 wxEvtHandler *wxWindow::GetEventHandler(void)
1547 {
1548 return m_eventHandler;
1549 }
1550
1551 void wxWindow::SetEventHandler( wxEvtHandler *handler )
1552 {
1553 m_eventHandler = handler;
1554 }
1555
1556 void wxWindow::PushEventHandler(wxEvtHandler *handler)
1557 {
1558 handler->SetNextHandler(GetEventHandler());
1559 SetEventHandler(handler);
1560 }
1561
1562 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
1563 {
1564 if ( GetEventHandler() )
1565 {
1566 wxEvtHandler *handlerA = GetEventHandler();
1567 wxEvtHandler *handlerB = handlerA->GetNextHandler();
1568 handlerA->SetNextHandler((wxEvtHandler *) NULL);
1569 SetEventHandler(handlerB);
1570 if ( deleteHandler )
1571 {
1572 delete handlerA;
1573 return (wxEvtHandler *) NULL;
1574 }
1575 else
1576 return handlerA;
1577 }
1578 else
1579 return (wxEvtHandler *) NULL;
1580 }
1581
1582 wxValidator *wxWindow::GetValidator(void)
1583 {
1584 return m_windowValidator;
1585 }
1586
1587 void wxWindow::SetValidator( const wxValidator& validator )
1588 {
1589 if (m_windowValidator) delete m_windowValidator;
1590 m_windowValidator = validator.Clone();
1591 if (m_windowValidator) m_windowValidator->SetWindow(this);
1592 }
1593
1594 bool wxWindow::IsBeingDeleted(void)
1595 {
1596 return FALSE;
1597 }
1598
1599 void wxWindow::SetId( wxWindowID id )
1600 {
1601 m_windowId = id;
1602 }
1603
1604 wxWindowID wxWindow::GetId(void)
1605 {
1606 return m_windowId;
1607 }
1608
1609 void wxWindow::SetCursor( const wxCursor &cursor )
1610 {
1611 wxASSERT(m_cursor != NULL);
1612
1613 if (m_cursor != NULL)
1614 if (*m_cursor == cursor)
1615 return;
1616 (*m_cursor) = cursor;
1617 if (m_widget->window)
1618 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
1619 if (m_wxwindow && m_wxwindow->window)
1620 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
1621 }
1622
1623 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
1624 {
1625 if (eraseBackground && m_wxwindow && m_wxwindow->window)
1626 {
1627 if (rect)
1628 gdk_window_clear_area( m_wxwindow->window,
1629 rect->x,
1630 rect->y,
1631 rect->width,
1632 rect->height );
1633 else
1634 Clear();
1635 }
1636 if (!rect)
1637 {
1638 if (m_wxwindow)
1639 {
1640 int w = 0;
1641 int h = 0;
1642 GetClientSize( &w, &h );
1643
1644 GdkRectangle gdk_rect;
1645 gdk_rect.x = 0;
1646 gdk_rect.y = 0;
1647 gdk_rect.width = w;
1648 gdk_rect.height = h;
1649 gtk_widget_draw( m_wxwindow, &gdk_rect );
1650 }
1651 }
1652 else
1653 {
1654 GdkRectangle gdk_rect;
1655 gdk_rect.x = rect->x;
1656 gdk_rect.y = rect->y;
1657 gdk_rect.width = rect->width;
1658 gdk_rect.height = rect->height;
1659
1660 if (m_wxwindow)
1661 gtk_widget_draw( m_wxwindow, &gdk_rect );
1662 else
1663 gtk_widget_draw( m_widget, &gdk_rect );
1664 }
1665 }
1666
1667 wxRegion wxWindow::GetUpdateRegion() const
1668 {
1669 return m_updateRegion;
1670 }
1671
1672 bool wxWindow::IsExposed( int x, int y) const
1673 {
1674 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
1675 }
1676
1677 bool wxWindow::IsExposed( int x, int y, int w, int h ) const
1678 {
1679 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
1680 }
1681
1682 bool wxWindow::IsExposed( const wxPoint& pt ) const
1683 {
1684 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
1685 }
1686
1687 bool wxWindow::IsExposed( const wxRect& rect ) const
1688 {
1689 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
1690 }
1691
1692 void wxWindow::Clear(void)
1693 {
1694 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
1695 }
1696
1697 wxColour wxWindow::GetBackgroundColour(void) const
1698 {
1699 return m_backgroundColour;
1700 }
1701
1702 void wxWindow::SetBackgroundColour( const wxColour &colour )
1703 {
1704 m_backgroundColour = colour;
1705 if (m_wxwindow)
1706 {
1707 m_backgroundColour.CalcPixel( m_wxwindow->style->colormap );
1708 gdk_window_set_background( m_wxwindow->window, m_backgroundColour.GetColor() );
1709 gdk_window_clear( m_wxwindow->window );
1710 }
1711 // do something ?
1712 }
1713
1714 wxColour wxWindow::GetForegroundColour(void) const
1715 {
1716 return m_foregroundColour;
1717 }
1718
1719 void wxWindow::SetForegroundColour( const wxColour &colour )
1720 {
1721 m_foregroundColour = colour;
1722 }
1723
1724 bool wxWindow::Validate(void)
1725 {
1726 wxNode *node = GetChildren()->First();
1727 while (node)
1728 {
1729 wxWindow *child = (wxWindow *)node->Data();
1730 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
1731 { return FALSE; }
1732 node = node->Next();
1733 }
1734 return TRUE;
1735 }
1736
1737 bool wxWindow::TransferDataToWindow(void)
1738 {
1739 wxNode *node = GetChildren()->First();
1740 while (node)
1741 {
1742 wxWindow *child = (wxWindow *)node->Data();
1743 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
1744 !child->GetValidator()->TransferToWindow() )
1745 {
1746 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
1747 return FALSE;
1748 }
1749 node = node->Next();
1750 }
1751 return TRUE;
1752 }
1753
1754 bool wxWindow::TransferDataFromWindow(void)
1755 {
1756 wxNode *node = GetChildren()->First();
1757 while (node)
1758 {
1759 wxWindow *child = (wxWindow *)node->Data();
1760 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
1761 { return FALSE; }
1762 node = node->Next();
1763 }
1764 return TRUE;
1765 }
1766
1767 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
1768 {
1769 m_acceleratorTable = accel;
1770 }
1771
1772 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
1773 {
1774 TransferDataToWindow();
1775 }
1776
1777 void wxWindow::InitDialog(void)
1778 {
1779 wxInitDialogEvent event(GetId());
1780 event.SetEventObject( this );
1781 GetEventHandler()->ProcessEvent(event);
1782 }
1783
1784 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
1785 {
1786 menu->SetInvokingWindow( win );
1787 wxNode *node = menu->m_items.First();
1788 while (node)
1789 {
1790 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
1791 if (menuitem->IsSubMenu())
1792 SetInvokingWindow( menuitem->GetSubMenu(), win );
1793 node = node->Next();
1794 }
1795 }
1796
1797 bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
1798 {
1799 SetInvokingWindow( menu, this );
1800 gtk_menu_popup( GTK_MENU(menu->m_menu), (GtkWidget *) NULL, (GtkWidget *) NULL, (GtkMenuPositionFunc) NULL, NULL, 0, 0 );
1801 return TRUE;
1802 }
1803
1804 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
1805 {
1806 GtkWidget *dnd_widget = GetConnectWidget();
1807
1808 if (m_pDropTarget)
1809 {
1810 gtk_signal_disconnect_by_func( GTK_OBJECT(dnd_widget),
1811 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
1812
1813 m_pDropTarget->UnregisterWidget( dnd_widget );
1814 delete m_pDropTarget;
1815 }
1816 m_pDropTarget = dropTarget;
1817 if (m_pDropTarget)
1818 {
1819 m_pDropTarget->RegisterWidget( dnd_widget );
1820
1821 gtk_signal_connect( GTK_OBJECT(dnd_widget), "drop_data_available_event",
1822 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
1823 }
1824 }
1825
1826 wxDropTarget *wxWindow::GetDropTarget() const
1827 {
1828 return m_pDropTarget;
1829 }
1830
1831 GtkWidget* wxWindow::GetConnectWidget(void)
1832 {
1833 GtkWidget *connect_widget = m_widget;
1834 if (m_wxwindow) connect_widget = m_wxwindow;
1835
1836 return connect_widget;
1837 }
1838
1839 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
1840 {
1841 if (m_wxwindow) return (window == m_wxwindow->window);
1842 return (window == m_widget->window);
1843 }
1844
1845 void wxWindow::SetFont( const wxFont &font )
1846 {
1847 m_font = font;
1848 /*
1849 create new style
1850 copy old style values to new one
1851 set font in new style
1852 -> takes to many resources
1853
1854 GtkStyle *style = gtk_style_new();
1855 ...
1856 */
1857 }
1858
1859 wxFont *wxWindow::GetFont(void)
1860 {
1861 return &m_font;
1862 }
1863
1864 void wxWindow::SetWindowStyleFlag( long flag )
1865 {
1866 m_windowStyle = flag;
1867 }
1868
1869 long wxWindow::GetWindowStyleFlag(void) const
1870 {
1871 return m_windowStyle;
1872 }
1873
1874 void wxWindow::CaptureMouse(void)
1875 {
1876 GtkWidget *connect_widget = GetConnectWidget();
1877 gtk_grab_add( connect_widget );
1878 gdk_pointer_grab ( connect_widget->window, FALSE,
1879 (GdkEventMask)
1880 (GDK_BUTTON_PRESS_MASK |
1881 GDK_BUTTON_RELEASE_MASK |
1882 GDK_POINTER_MOTION_MASK),
1883 (GdkWindow *) NULL, (GdkCursor *) NULL, GDK_CURRENT_TIME );
1884 }
1885
1886 void wxWindow::ReleaseMouse(void)
1887 {
1888 GtkWidget *connect_widget = GetConnectWidget();
1889 gtk_grab_remove( connect_widget );
1890 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
1891 }
1892
1893 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
1894 {
1895 }
1896
1897 wxString wxWindow::GetTitle(void) const
1898 {
1899 return (wxString&)m_windowName;
1900 }
1901
1902 wxString wxWindow::GetLabel(void) const
1903 {
1904 return GetTitle();
1905 }
1906
1907 void wxWindow::SetName( const wxString &name )
1908 {
1909 m_windowName = name;
1910 }
1911
1912 wxString wxWindow::GetName(void) const
1913 {
1914 return (wxString&)m_windowName;
1915 }
1916
1917 bool wxWindow::IsShown(void) const
1918 {
1919 return m_isShown;
1920 }
1921
1922 bool wxWindow::IsRetained(void)
1923 {
1924 return FALSE;
1925 }
1926
1927 wxWindow *wxWindow::FindWindow( long id )
1928 {
1929 if (id == m_windowId) return this;
1930 wxNode *node = m_children.First();
1931 while (node)
1932 {
1933 wxWindow *child = (wxWindow*)node->Data();
1934 wxWindow *res = child->FindWindow( id );
1935 if (res) return res;
1936 node = node->Next();
1937 }
1938 return (wxWindow *) NULL;
1939 }
1940
1941 wxWindow *wxWindow::FindWindow( const wxString& name )
1942 {
1943 if (name == m_windowName) return this;
1944 wxNode *node = m_children.First();
1945 while (node)
1946 {
1947 wxWindow *child = (wxWindow*)node->Data();
1948 wxWindow *res = child->FindWindow( name );
1949 if (res) return res;
1950 node = node->Next();
1951 }
1952 return (wxWindow *) NULL;
1953 }
1954
1955 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
1956 int range, bool WXUNUSED(refresh) )
1957 {
1958 if (!m_wxwindow) return;
1959
1960 if (orient == wxHORIZONTAL)
1961 {
1962 float fpos = (float)pos;
1963 m_oldHorizontalPos = fpos;
1964 float frange = (float)range;
1965 float fthumb = (float)thumbVisible;
1966
1967 if ((fabs(fpos-m_hAdjust->value) < 0.2) &&
1968 (fabs(frange-m_hAdjust->upper) < 0.2) &&
1969 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
1970 return;
1971
1972 m_hAdjust->lower = 0.0;
1973 m_hAdjust->upper = frange;
1974 m_hAdjust->value = fpos;
1975 m_hAdjust->step_increment = 1.0;
1976 m_hAdjust->page_increment = (float)(wxMax(fthumb-2,0));
1977 m_hAdjust->page_size = fthumb;
1978 }
1979 else
1980 {
1981 float fpos = (float)pos;
1982 m_oldVerticalPos = fpos;
1983 float frange = (float)range;
1984 float fthumb = (float)thumbVisible;
1985
1986 if ((fabs(fpos-m_vAdjust->value) < 0.2) &&
1987 (fabs(frange-m_vAdjust->upper) < 0.2) &&
1988 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
1989 return;
1990
1991 m_vAdjust->lower = 0.0;
1992 m_vAdjust->upper = frange;
1993 m_vAdjust->value = fpos;
1994 m_vAdjust->step_increment = 1.0;
1995 m_vAdjust->page_increment = (float)(wxMax(fthumb-2,0));
1996 m_vAdjust->page_size = fthumb;
1997 }
1998
1999 if (m_wxwindow->window)
2000 {
2001 if (orient == wxHORIZONTAL)
2002 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2003 else
2004 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2005
2006 gtk_widget_set_usize( m_widget, m_width, m_height );
2007 }
2008 }
2009
2010 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
2011 {
2012 if (!m_wxwindow) return;
2013
2014 if (orient == wxHORIZONTAL)
2015 {
2016 float fpos = (float)pos;
2017 m_oldHorizontalPos = fpos;
2018
2019 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2020 m_hAdjust->value = fpos;
2021 }
2022 else
2023 {
2024 float fpos = (float)pos;
2025 m_oldVerticalPos = fpos;
2026 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2027 m_vAdjust->value = fpos;
2028 }
2029
2030 if (m_wxwindow->window)
2031 {
2032 if (orient == wxHORIZONTAL)
2033 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2034 else
2035 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2036 }
2037 }
2038
2039 int wxWindow::GetScrollThumb( int orient ) const
2040 {
2041 if (!m_wxwindow) return 0;
2042
2043 if (orient == wxHORIZONTAL)
2044 return (int)(m_hAdjust->page_size+0.5);
2045 else
2046 return (int)(m_vAdjust->page_size+0.5);
2047 }
2048
2049 int wxWindow::GetScrollPos( int orient ) const
2050 {
2051 if (!m_wxwindow) return 0;
2052
2053 if (orient == wxHORIZONTAL)
2054 return (int)(m_hAdjust->value+0.5);
2055 else
2056 return (int)(m_vAdjust->value+0.5);
2057 }
2058
2059 int wxWindow::GetScrollRange( int orient ) const
2060 {
2061 if (!m_wxwindow) return 0;
2062
2063 if (orient == wxHORIZONTAL)
2064 return (int)(m_hAdjust->upper+0.5);
2065 else
2066 return (int)(m_vAdjust->upper+0.5);
2067 }
2068
2069 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
2070 {
2071 if (!m_wxwindow) return;
2072
2073 /*
2074 bool refresh = FALSE;
2075
2076 if ((m_drawingOffsetX == 0) && (m_drawingOffsetY == 0))
2077 {
2078 m_drawingOffsetX = -16000;
2079 m_drawingOffsetY = -16000;
2080 refresh = TRUE;
2081 }
2082 else
2083 {
2084 m_drawingOffsetX += dx;
2085 m_drawingOffsetY += dy;
2086 }
2087
2088 // printf( "X: %d Y: %d \n", (int)m_drawingOffsetX, (int)m_drawingOffsetY );
2089
2090 gtk_myfixed_set_offset( GTK_MYFIXED(m_wxwindow), m_drawingOffsetX, m_drawingOffsetY );
2091
2092 if (refresh) Refresh();
2093
2094 The code here is very nifty, but it doesn't work with
2095 overlapping windows...
2096 */
2097
2098 int cw = 0;
2099 int ch = 0;
2100 GetClientSize( &cw, &ch );
2101
2102 int w = cw - abs(dx);
2103 int h = ch - abs(dy);
2104 if ((h < 0) || (w < 0))
2105 {
2106 Refresh();
2107 return;
2108 }
2109 int s_x = 0;
2110 int s_y = 0;
2111 if (dx < 0) s_x = -dx;
2112 if (dy < 0) s_y = -dy;
2113 int d_x = 0;
2114 int d_y = 0;
2115 if (dx > 0) d_x = dx;
2116 if (dy > 0) d_y = dy;
2117 gdk_window_copy_area( m_wxwindow->window, m_wxwindow->style->fg_gc[0], d_x, d_y,
2118 m_wxwindow->window, s_x, s_y, w, h );
2119
2120 wxRect rect;
2121 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2122 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2123 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2124 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
2125
2126 Refresh( TRUE, &rect );
2127 }
2128
2129 //-------------------------------------------------------------------------------------
2130 // Layout
2131 //-------------------------------------------------------------------------------------
2132
2133 wxLayoutConstraints *wxWindow::GetConstraints(void) const
2134 {
2135 return m_constraints;
2136 }
2137
2138 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
2139 {
2140 if (m_constraints)
2141 {
2142 UnsetConstraints(m_constraints);
2143 delete m_constraints;
2144 }
2145 m_constraints = constraints;
2146 if (m_constraints)
2147 {
2148 // Make sure other windows know they're part of a 'meaningful relationship'
2149 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
2150 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2151 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
2152 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2153 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
2154 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2155 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
2156 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2157 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
2158 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2159 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
2160 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2161 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
2162 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2163 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
2164 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2165 }
2166 ;
2167 }
2168 ;
2169
2170 void wxWindow::SetAutoLayout( bool autoLayout )
2171 {
2172 m_autoLayout = autoLayout;
2173 }
2174
2175 bool wxWindow::GetAutoLayout(void) const
2176 {
2177 return m_autoLayout;
2178 }
2179
2180 wxSizer *wxWindow::GetSizer(void) const
2181 {
2182 return m_windowSizer;
2183 }
2184
2185 void wxWindow::SetSizerParent( wxWindow *win )
2186 {
2187 m_sizerParent = win;
2188 }
2189
2190 wxWindow *wxWindow::GetSizerParent(void) const
2191 {
2192 return m_sizerParent;
2193 }
2194
2195 // This removes any dangling pointers to this window
2196 // in other windows' constraintsInvolvedIn lists.
2197 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
2198 {
2199 if (c)
2200 {
2201 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2202 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2203 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2204 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2205 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
2206 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2207 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
2208 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2209 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
2210 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2211 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
2212 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2213 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
2214 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2215 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
2216 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2217 }
2218 }
2219
2220 // Back-pointer to other windows we're involved with, so if we delete
2221 // this window, we must delete any constraints we're involved with.
2222 void wxWindow::AddConstraintReference(wxWindow *otherWin)
2223 {
2224 if (!m_constraintsInvolvedIn)
2225 m_constraintsInvolvedIn = new wxList;
2226 if (!m_constraintsInvolvedIn->Member(otherWin))
2227 m_constraintsInvolvedIn->Append(otherWin);
2228 }
2229
2230 // REMOVE back-pointer to other windows we're involved with.
2231 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
2232 {
2233 if (m_constraintsInvolvedIn)
2234 m_constraintsInvolvedIn->DeleteObject(otherWin);
2235 }
2236
2237 // Reset any constraints that mention this window
2238 void wxWindow::DeleteRelatedConstraints(void)
2239 {
2240 if (m_constraintsInvolvedIn)
2241 {
2242 wxNode *node = m_constraintsInvolvedIn->First();
2243 while (node)
2244 {
2245 wxWindow *win = (wxWindow *)node->Data();
2246 wxNode *next = node->Next();
2247 wxLayoutConstraints *constr = win->GetConstraints();
2248
2249 // Reset any constraints involving this window
2250 if (constr)
2251 {
2252 constr->left.ResetIfWin((wxWindow *)this);
2253 constr->top.ResetIfWin((wxWindow *)this);
2254 constr->right.ResetIfWin((wxWindow *)this);
2255 constr->bottom.ResetIfWin((wxWindow *)this);
2256 constr->width.ResetIfWin((wxWindow *)this);
2257 constr->height.ResetIfWin((wxWindow *)this);
2258 constr->centreX.ResetIfWin((wxWindow *)this);
2259 constr->centreY.ResetIfWin((wxWindow *)this);
2260 }
2261 delete node;
2262 node = next;
2263 }
2264 delete m_constraintsInvolvedIn;
2265 m_constraintsInvolvedIn = (wxList *) NULL;
2266 }
2267 }
2268
2269 void wxWindow::SetSizer(wxSizer *sizer)
2270 {
2271 m_windowSizer = sizer;
2272 if (sizer)
2273 sizer->SetSizerParent((wxWindow *)this);
2274 }
2275
2276 /*
2277 * New version
2278 */
2279
2280 bool wxWindow::Layout(void)
2281 {
2282 if (GetConstraints())
2283 {
2284 int w, h;
2285 GetClientSize(&w, &h);
2286 GetConstraints()->width.SetValue(w);
2287 GetConstraints()->height.SetValue(h);
2288 }
2289
2290 // If top level (one sizer), evaluate the sizer's constraints.
2291 if (GetSizer())
2292 {
2293 int noChanges;
2294 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2295 GetSizer()->LayoutPhase1(&noChanges);
2296 GetSizer()->LayoutPhase2(&noChanges);
2297 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2298 return TRUE;
2299 }
2300 else
2301 {
2302 // Otherwise, evaluate child constraints
2303 ResetConstraints(); // Mark all constraints as unevaluated
2304 DoPhase(1); // Just one phase need if no sizers involved
2305 DoPhase(2);
2306 SetConstraintSizes(); // Recursively set the real window sizes
2307 }
2308 return TRUE;
2309 }
2310
2311
2312 // Do a phase of evaluating constraints:
2313 // the default behaviour. wxSizers may do a similar
2314 // thing, but also impose their own 'constraints'
2315 // and order the evaluation differently.
2316 bool wxWindow::LayoutPhase1(int *noChanges)
2317 {
2318 wxLayoutConstraints *constr = GetConstraints();
2319 if (constr)
2320 {
2321 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
2322 }
2323 else
2324 return TRUE;
2325 }
2326
2327 bool wxWindow::LayoutPhase2(int *noChanges)
2328 {
2329 *noChanges = 0;
2330
2331 // Layout children
2332 DoPhase(1);
2333 DoPhase(2);
2334 return TRUE;
2335 }
2336
2337 // Do a phase of evaluating child constraints
2338 bool wxWindow::DoPhase(int phase)
2339 {
2340 int noIterations = 0;
2341 int maxIterations = 500;
2342 int noChanges = 1;
2343 int noFailures = 0;
2344 wxList succeeded;
2345 while ((noChanges > 0) && (noIterations < maxIterations))
2346 {
2347 noChanges = 0;
2348 noFailures = 0;
2349 wxNode *node = GetChildren()->First();
2350 while (node)
2351 {
2352 wxWindow *child = (wxWindow *)node->Data();
2353 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
2354 {
2355 wxLayoutConstraints *constr = child->GetConstraints();
2356 if (constr)
2357 {
2358 if (succeeded.Member(child))
2359 {
2360 }
2361 else
2362 {
2363 int tempNoChanges = 0;
2364 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
2365 noChanges += tempNoChanges;
2366 if (success)
2367 {
2368 succeeded.Append(child);
2369 }
2370 }
2371 }
2372 }
2373 node = node->Next();
2374 }
2375 noIterations ++;
2376 }
2377 return TRUE;
2378 }
2379
2380 void wxWindow::ResetConstraints(void)
2381 {
2382 wxLayoutConstraints *constr = GetConstraints();
2383 if (constr)
2384 {
2385 constr->left.SetDone(FALSE);
2386 constr->top.SetDone(FALSE);
2387 constr->right.SetDone(FALSE);
2388 constr->bottom.SetDone(FALSE);
2389 constr->width.SetDone(FALSE);
2390 constr->height.SetDone(FALSE);
2391 constr->centreX.SetDone(FALSE);
2392 constr->centreY.SetDone(FALSE);
2393 }
2394 wxNode *node = GetChildren()->First();
2395 while (node)
2396 {
2397 wxWindow *win = (wxWindow *)node->Data();
2398 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2399 win->ResetConstraints();
2400 node = node->Next();
2401 }
2402 }
2403
2404 // Need to distinguish between setting the 'fake' size for
2405 // windows and sizers, and setting the real values.
2406 void wxWindow::SetConstraintSizes(bool recurse)
2407 {
2408 wxLayoutConstraints *constr = GetConstraints();
2409 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
2410 constr->width.GetDone() && constr->height.GetDone())
2411 {
2412 int x = constr->left.GetValue();
2413 int y = constr->top.GetValue();
2414 int w = constr->width.GetValue();
2415 int h = constr->height.GetValue();
2416
2417 // If we don't want to resize this window, just move it...
2418 if ((constr->width.GetRelationship() != wxAsIs) ||
2419 (constr->height.GetRelationship() != wxAsIs))
2420 {
2421 // Calls Layout() recursively. AAAGH. How can we stop that.
2422 // Simply take Layout() out of non-top level OnSizes.
2423 SizerSetSize(x, y, w, h);
2424 }
2425 else
2426 {
2427 SizerMove(x, y);
2428 }
2429 }
2430 else if (constr)
2431 {
2432 char *windowClass = this->GetClassInfo()->GetClassName();
2433
2434 wxString winName;
2435 if (GetName() == "")
2436 winName = _("unnamed");
2437 else
2438 winName = GetName();
2439 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass, (const char *)winName);
2440 if (!constr->left.GetDone())
2441 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2442 if (!constr->right.GetDone())
2443 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2444 if (!constr->width.GetDone())
2445 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2446 if (!constr->height.GetDone())
2447 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2448 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2449 }
2450
2451 if (recurse)
2452 {
2453 wxNode *node = GetChildren()->First();
2454 while (node)
2455 {
2456 wxWindow *win = (wxWindow *)node->Data();
2457 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2458 win->SetConstraintSizes();
2459 node = node->Next();
2460 }
2461 }
2462 }
2463
2464 // This assumes that all sizers are 'on' the same
2465 // window, i.e. the parent of this window.
2466 void wxWindow::TransformSizerToActual(int *x, int *y) const
2467 {
2468 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
2469 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
2470 return;
2471
2472 int xp, yp;
2473 m_sizerParent->GetPosition(&xp, &yp);
2474 m_sizerParent->TransformSizerToActual(&xp, &yp);
2475 *x += xp;
2476 *y += yp;
2477 }
2478
2479 void wxWindow::SizerSetSize(int x, int y, int w, int h)
2480 {
2481 int xx = x;
2482 int yy = y;
2483 TransformSizerToActual(&xx, &yy);
2484 SetSize(xx, yy, w, h);
2485 }
2486
2487 void wxWindow::SizerMove(int x, int y)
2488 {
2489 int xx = x;
2490 int yy = y;
2491 TransformSizerToActual(&xx, &yy);
2492 Move(xx, yy);
2493 }
2494
2495 // Only set the size/position of the constraint (if any)
2496 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
2497 {
2498 wxLayoutConstraints *constr = GetConstraints();
2499 if (constr)
2500 {
2501 if (x != -1)
2502 {
2503 constr->left.SetValue(x);
2504 constr->left.SetDone(TRUE);
2505 }
2506 if (y != -1)
2507 {
2508 constr->top.SetValue(y);
2509 constr->top.SetDone(TRUE);
2510 }
2511 if (w != -1)
2512 {
2513 constr->width.SetValue(w);
2514 constr->width.SetDone(TRUE);
2515 }
2516 if (h != -1)
2517 {
2518 constr->height.SetValue(h);
2519 constr->height.SetDone(TRUE);
2520 }
2521 }
2522 }
2523
2524 void wxWindow::MoveConstraint(int x, int y)
2525 {
2526 wxLayoutConstraints *constr = GetConstraints();
2527 if (constr)
2528 {
2529 if (x != -1)
2530 {
2531 constr->left.SetValue(x);
2532 constr->left.SetDone(TRUE);
2533 }
2534 if (y != -1)
2535 {
2536 constr->top.SetValue(y);
2537 constr->top.SetDone(TRUE);
2538 }
2539 }
2540 }
2541
2542 void wxWindow::GetSizeConstraint(int *w, int *h) const
2543 {
2544 wxLayoutConstraints *constr = GetConstraints();
2545 if (constr)
2546 {
2547 *w = constr->width.GetValue();
2548 *h = constr->height.GetValue();
2549 }
2550 else
2551 GetSize(w, h);
2552 }
2553
2554 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
2555 {
2556 wxLayoutConstraints *constr = GetConstraints();
2557 if (constr)
2558 {
2559 *w = constr->width.GetValue();
2560 *h = constr->height.GetValue();
2561 }
2562 else
2563 GetClientSize(w, h);
2564 }
2565
2566 void wxWindow::GetPositionConstraint(int *x, int *y) const
2567 {
2568 wxLayoutConstraints *constr = GetConstraints();
2569 if (constr)
2570 {
2571 *x = constr->left.GetValue();
2572 *y = constr->top.GetValue();
2573 }
2574 else
2575 GetPosition(x, y);
2576 }
2577
2578 bool wxWindow::AcceptsFocus() const
2579 {
2580 return IsEnabled() && IsShown();
2581 }
2582
2583 void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) )
2584 {
2585 UpdateWindowUI();
2586 }