]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/frame.cpp
Fixed a bug which sometimes lead to windows
[wxWidgets.git] / src / gtk / frame.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: frame.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "frame.h"
12 #endif
13
14 #include "wx/frame.h"
15 #include "wx/dialog.h"
16 #include "wx/control.h"
17 #include "wx/app.h"
18 #include "wx/menu.h"
19 #include "wx/toolbar.h"
20 #include "wx/statusbr.h"
21 #include "wx/dcclient.h"
22
23 #include "glib.h"
24 #include "gdk/gdk.h"
25 #include "gtk/gtk.h"
26 #include "wx/gtk/win_gtk.h"
27
28 //-----------------------------------------------------------------------------
29 // constants
30 //-----------------------------------------------------------------------------
31
32 const int wxMENU_HEIGHT = 27;
33 const int wxSTATUS_HEIGHT = 25;
34 const int wxPLACE_HOLDER = 0;
35
36 //-----------------------------------------------------------------------------
37 // idle system
38 //-----------------------------------------------------------------------------
39
40 extern void wxapp_install_idle_handler();
41 extern bool g_isIdle;
42
43 //-----------------------------------------------------------------------------
44 // data
45 //-----------------------------------------------------------------------------
46
47 extern wxList wxPendingDelete;
48
49 //-----------------------------------------------------------------------------
50 // debug
51 //-----------------------------------------------------------------------------
52
53 #ifdef __WXDEBUG__
54
55 extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window );
56
57 #endif
58
59 //-----------------------------------------------------------------------------
60 // "size_allocate"
61 //-----------------------------------------------------------------------------
62
63 static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxFrame *win )
64 {
65 if (g_isIdle) wxapp_install_idle_handler();
66
67 if (!win->HasVMT()) return;
68
69 /*
70 printf( "OnFrameResize from " );
71 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
72 printf( win->GetClassInfo()->GetClassName() );
73 printf( ".\n" );
74 */
75
76 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
77 {
78 win->m_sizeSet = FALSE;
79 win->m_width = alloc->width;
80 win->m_height = alloc->height;
81 }
82 }
83
84 //-----------------------------------------------------------------------------
85 // "delete_event"
86 //-----------------------------------------------------------------------------
87
88 static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxFrame *win )
89 {
90 if (g_isIdle) wxapp_install_idle_handler();
91
92 /*
93 printf( "OnDelete from " );
94 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
95 printf( win->GetClassInfo()->GetClassName() );
96 printf( ".\n" );
97 */
98
99 win->Close();
100
101 return TRUE;
102 }
103
104 //-----------------------------------------------------------------------------
105 // "child_attached" of menu bar
106 //-----------------------------------------------------------------------------
107
108 static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
109 {
110 if (g_isIdle) wxapp_install_idle_handler();
111
112 if (!win->HasVMT()) return;
113
114 win->m_menuBarDetached = FALSE;
115 win->m_sizeSet = FALSE;
116 }
117
118 //-----------------------------------------------------------------------------
119 // "child_detached" of menu bar
120 //-----------------------------------------------------------------------------
121
122 static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
123 {
124 if (g_isIdle) wxapp_install_idle_handler();
125
126 if (!win->HasVMT()) return;
127
128 win->m_menuBarDetached = TRUE;
129 win->m_sizeSet = FALSE;
130 }
131
132 //-----------------------------------------------------------------------------
133 // "child_attached" of tool bar
134 //-----------------------------------------------------------------------------
135
136 static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
137 {
138 if (g_isIdle) wxapp_install_idle_handler();
139
140 if (!win->HasVMT()) return;
141
142 win->m_toolBarDetached = FALSE;
143 win->m_sizeSet = FALSE;
144 }
145
146 //-----------------------------------------------------------------------------
147 // "child_detached" of tool bar
148 //-----------------------------------------------------------------------------
149
150 static void gtk_toolbar_detached_callback( GtkWidget *widget, GtkWidget *WXUNUSED(child), wxFrame *win )
151 {
152 if (g_isIdle) wxapp_install_idle_handler();
153
154 if (!win->HasVMT()) return;
155
156 win->m_toolBarDetached = TRUE;
157 win->m_sizeSet = FALSE;
158 }
159
160 //-----------------------------------------------------------------------------
161 // "configure_event"
162 //-----------------------------------------------------------------------------
163
164 static gint gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *event, wxFrame *win )
165 {
166 if (g_isIdle) wxapp_install_idle_handler();
167
168 if (!win->HasVMT()) return FALSE;
169
170 win->m_x = event->x;
171 win->m_y = event->y;
172
173 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
174 mevent.SetEventObject( win );
175 win->GetEventHandler()->ProcessEvent( mevent );
176
177 return FALSE;
178 }
179
180 //-----------------------------------------------------------------------------
181 // "realize" from m_widget
182 //-----------------------------------------------------------------------------
183
184 /* we cannot MWM hints and icons before the widget has been realized,
185 so we do this directly after realization */
186
187 static gint
188 gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win )
189 {
190 if (g_isIdle) wxapp_install_idle_handler();
191
192 /* all this is for Motif Window Manager "hints" and is supposed to be
193 recognized by other WM as well. not tested. */
194 long decor = (long) GDK_DECOR_ALL;
195 long func = (long) GDK_FUNC_ALL;
196
197 if ((win->m_windowStyle & wxCAPTION) == 0)
198 decor |= GDK_DECOR_TITLE;
199 if ((win->m_windowStyle & wxSYSTEM_MENU) == 0)
200 decor |= GDK_DECOR_MENU;
201 if ((win->m_windowStyle & wxMINIMIZE_BOX) == 0)
202 {
203 func |= GDK_FUNC_MINIMIZE;
204 decor |= GDK_DECOR_MINIMIZE;
205 }
206 if ((win->m_windowStyle & wxMAXIMIZE_BOX) == 0)
207 {
208 func |= GDK_FUNC_MAXIMIZE;
209 decor |= GDK_DECOR_MAXIMIZE;
210 }
211 if ((win->m_windowStyle & wxRESIZE_BORDER) == 0)
212 func |= GDK_FUNC_RESIZE;
213
214 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor);
215 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func);
216
217 /* GTK's shrinking/growing policy */
218 if ((win->m_windowStyle & wxRESIZE_BORDER) == 0)
219 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
220 else
221 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
222
223 /* reset the icon */
224 if (win->m_icon != wxNullIcon)
225 {
226 wxIcon icon( win->m_icon );
227 win->m_icon = wxNullIcon;
228 win->SetIcon( icon );
229 }
230
231 /* we set the focus to the child that accepts the focus. this
232 doesn't really have to be done in "realize" but why not? */
233 wxNode *node = win->m_children.First();
234 while (node)
235 {
236 wxWindow *child = (wxWindow*) node->Data();
237 if (child->AcceptsFocus())
238 {
239 child->SetFocus();
240 break;
241 }
242
243 node = node->Next();
244 }
245
246 return FALSE;
247 }
248
249 //-----------------------------------------------------------------------------
250 // InsertChild for wxFrame
251 //-----------------------------------------------------------------------------
252
253 /* Callback for wxFrame. This very strange beast has to be used because
254 * C++ has no virtual methods in a constructor. We have to emulate a
255 * virtual function here as wxWindows requires different ways to insert
256 * a child in container classes. */
257
258 static void wxInsertChildInFrame( wxWindow* parent, wxWindow* child )
259 {
260 if (wxIS_KIND_OF(child,wxToolBar) || wxIS_KIND_OF(child,wxMenuBar))
261 {
262 /* actually, menubars are never inserted here, but this
263 may change one day */
264
265 /* these are outside the client area */
266 wxFrame* frame = (wxFrame*) parent;
267 gtk_myfixed_put( GTK_MYFIXED(frame->m_mainWidget),
268 GTK_WIDGET(child->m_widget),
269 child->m_x,
270 child->m_y );
271
272 /* we connect to these events for recalculating the client area
273 space when the toolbar is floating */
274 if (wxIS_KIND_OF(child,wxToolBar))
275 {
276 wxToolBar *toolBar = (wxToolBar*) child;
277 if (toolBar->m_windowStyle & wxTB_DOCKABLE)
278 {
279 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_attached",
280 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback), (gpointer)parent );
281
282 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_detached",
283 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback), (gpointer)parent );
284 }
285 }
286 }
287 else
288 {
289 /* these are inside the client area */
290 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
291 GTK_WIDGET(child->m_widget),
292 child->m_x,
293 child->m_y );
294 }
295
296 gtk_widget_set_usize( GTK_WIDGET(child->m_widget),
297 child->m_width,
298 child->m_height );
299
300 /* resize on OnInternalIdle */
301 parent->m_sizeSet = FALSE;
302 }
303
304 //-----------------------------------------------------------------------------
305 // wxFrame
306 //-----------------------------------------------------------------------------
307
308 BEGIN_EVENT_TABLE(wxFrame, wxWindow)
309 EVT_SIZE(wxFrame::OnSize)
310 EVT_CLOSE(wxFrame::OnCloseWindow)
311 EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight)
312 END_EVENT_TABLE()
313
314 IMPLEMENT_DYNAMIC_CLASS(wxFrame,wxWindow)
315
316 wxFrame::wxFrame()
317 {
318 m_frameMenuBar = (wxMenuBar *) NULL;
319 m_frameStatusBar = (wxStatusBar *) NULL;
320 m_frameToolBar = (wxToolBar *) NULL;
321 m_sizeSet = FALSE;
322 m_miniEdge = 0;
323 m_miniTitle = 0;
324 m_mainWidget = (GtkWidget*) NULL;
325 m_menuBarDetached = FALSE;
326 m_toolBarDetached = FALSE;
327 m_insertCallback = wxInsertChildInFrame;
328 }
329
330 wxFrame::wxFrame( wxWindow *parent, wxWindowID id, const wxString &title,
331 const wxPoint &pos, const wxSize &size,
332 long style, const wxString &name )
333 {
334 m_frameMenuBar = (wxMenuBar *) NULL;
335 m_frameStatusBar = (wxStatusBar *) NULL;
336 m_frameToolBar = (wxToolBar *) NULL;
337 m_sizeSet = FALSE;
338 m_miniEdge = 0;
339 m_miniTitle = 0;
340 m_mainWidget = (GtkWidget*) NULL;
341 m_menuBarDetached = FALSE;
342 m_toolBarDetached = FALSE;
343 m_insertCallback = wxInsertChildInFrame;
344 Create( parent, id, title, pos, size, style, name );
345 }
346
347 bool wxFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
348 const wxPoint &pos, const wxSize &size,
349 long style, const wxString &name )
350 {
351 wxTopLevelWindows.Append( this );
352
353 m_needParent = FALSE;
354
355 PreCreation( parent, id, pos, size, style, name );
356
357 m_title = title;
358
359 m_insertCallback = wxInsertChildInFrame;
360
361 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
362 if (style & wxSIMPLE_BORDER) win_type = GTK_WINDOW_POPUP;
363
364 m_widget = gtk_window_new( win_type );
365
366 #ifdef __WXDEBUG__
367 debug_focus_in( m_widget, _T("wxFrame::m_widget"), name );
368 #endif
369
370 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
371 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
372
373 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
374 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
375
376 /* m_mainWidget holds the toolbar, the menubar and the client area */
377 m_mainWidget = gtk_myfixed_new();
378 gtk_widget_show( m_mainWidget );
379 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
380 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
381
382 #ifdef __WXDEBUG__
383 debug_focus_in( m_mainWidget, _T("wxFrame::m_mainWidget"), name );
384 #endif
385
386 /* m_wxwindow only represents the client area without toolbar and menubar */
387 m_wxwindow = gtk_myfixed_new();
388 gtk_widget_show( m_wxwindow );
389 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
390
391 #ifdef __WXDEBUG__
392 debug_focus_in( m_wxwindow, _T("wxFrame::m_wxwindow"), name );
393 #endif
394
395 /* we donm't allow the frame to get the focus as otherwise
396 the frame will grabit at arbitrary fcous changes. */
397 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
398
399 if (m_parent) m_parent->AddChild( this );
400
401 PostCreation();
402
403 /* we cannot set MWM hints and icons before the widget has
404 been realized, so we do this directly after realization */
405 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
406 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
407
408 /* the user resized the frame by dragging etc. */
409 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
410 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
411
412 /* the only way to get the window size is to connect to this event */
413 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
414 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
415
416 return TRUE;
417 }
418
419 wxFrame::~wxFrame()
420 {
421 if (m_frameMenuBar) delete m_frameMenuBar;
422 m_frameMenuBar = (wxMenuBar *) NULL;
423
424 if (m_frameStatusBar) delete m_frameStatusBar;
425 m_frameStatusBar = (wxStatusBar *) NULL;
426
427 if (m_frameToolBar) delete m_frameToolBar;
428 m_frameToolBar = (wxToolBar *) NULL;
429
430 wxTopLevelWindows.DeleteObject( this );
431
432 if (wxTheApp->GetTopWindow() == this)
433 wxTheApp->SetTopWindow( (wxWindow*) NULL );
434
435 if (wxTopLevelWindows.Number() == 0)
436 wxTheApp->ExitMainLoop();
437 }
438
439 bool wxFrame::Show( bool show )
440 {
441 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
442
443 if (show && !m_sizeSet)
444 {
445 /* by calling GtkOnSize here, we don't have to call
446 either after showing the frame, which would entail
447 much ugly flicker or from within the size_allocate
448 handler, because GTK 1.1.X forbids that. */
449
450 GtkOnSize( m_x, m_y, m_width, m_height );
451 }
452
453 return wxWindow::Show( show );
454 }
455
456 bool wxFrame::Destroy()
457 {
458 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
459
460 if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this);
461
462 return TRUE;
463 }
464
465 void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
466 {
467 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
468
469 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
470 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
471
472 /* avoid recursions */
473 if (m_resizing) return;
474 m_resizing = TRUE;
475
476 int old_x = m_x;
477 int old_y = m_y;
478 int old_width = m_width;
479 int old_height = m_height;
480
481 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
482 {
483 if (x != -1) m_x = x;
484 if (y != -1) m_y = y;
485 if (width != -1) m_width = width;
486 if (height != -1) m_height = height;
487 }
488 else
489 {
490 m_x = x;
491 m_y = y;
492 m_width = width;
493 m_height = height;
494 }
495
496 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
497 {
498 if (width == -1) m_width = 80;
499 }
500
501 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
502 {
503 if (height == -1) m_height = 26;
504 }
505
506 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
507 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
508 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
509 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
510
511 if ((m_x != -1) || (m_y != -1))
512 {
513 if ((m_x != old_x) || (m_y != old_y))
514 {
515 /* we set the size here and in gtk_frame_map_callback */
516 gtk_widget_set_uposition( m_widget, m_x, m_y );
517 }
518 }
519
520 if ((m_width != old_width) || (m_height != old_height))
521 {
522 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
523 done either directly before the frame is shown or in idle time
524 so that different calls to SetSize() don't lead to flicker. */
525 m_sizeSet = FALSE;
526 }
527
528 m_resizing = FALSE;
529 }
530
531 void wxFrame::Centre( int direction )
532 {
533 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
534
535 int x = 0;
536 int y = 0;
537
538 if ((direction & wxHORIZONTAL) == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
539 if ((direction & wxVERTICAL) == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
540
541 Move( x, y );
542 }
543
544 void wxFrame::GetClientSize( int *width, int *height ) const
545 {
546 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
547
548 wxWindow::GetClientSize( width, height );
549 if (height)
550 {
551 /* menu bar */
552 if (m_frameMenuBar)
553 {
554 if (!m_menuBarDetached)
555 (*height) -= wxMENU_HEIGHT;
556 else
557 (*height) -= wxPLACE_HOLDER;
558 }
559
560 /* status bar */
561 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
562
563 /* tool bar */
564 if (m_frameToolBar)
565 {
566 if (!m_toolBarDetached)
567 {
568 int y = 0;
569 m_frameToolBar->GetSize( (int *) NULL, &y );
570 (*height) -= y;
571 }
572 else
573 (*height) -= wxPLACE_HOLDER;
574 }
575
576 /* mini edge */
577 (*height) -= m_miniEdge*2 + m_miniTitle;
578 }
579 if (width)
580 {
581 (*width) -= m_miniEdge*2;
582 }
583 }
584
585 void wxFrame::DoSetClientSize( int width, int height )
586 {
587 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
588
589 /* menu bar */
590 if (m_frameMenuBar)
591 {
592 if (!m_menuBarDetached)
593 height += wxMENU_HEIGHT;
594 else
595 height += wxPLACE_HOLDER;
596 }
597
598 /* status bar */
599 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
600
601 /* tool bar */
602 if (m_frameToolBar)
603 {
604 if (!m_toolBarDetached)
605 {
606 int y = 0;
607 m_frameToolBar->GetSize( (int *) NULL, &y );
608 height += y;
609 }
610 else
611 height += wxPLACE_HOLDER;
612 }
613
614 wxWindow::DoSetClientSize( width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle );
615 }
616
617 void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int width, int height )
618 {
619 // due to a bug in gtk, x,y are always 0
620 // m_x = x;
621 // m_y = y;
622
623 /* avoid recursions */
624 if (m_resizing) return;
625 m_resizing = TRUE;
626
627 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
628 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
629
630 m_width = width;
631 m_height = height;
632
633 /* space occupied by m_frameToolBar and m_frameMenuBar */
634 int client_area_y_offset = 0;
635
636 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
637 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
638 set in wxFrame::Create so it is used to check what kind of frame we
639 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
640 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
641 importantly) m_mainWidget */
642
643 if (m_mainWidget)
644 {
645 /* check if size is in legal range */
646 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
647 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
648 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
649 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
650
651 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
652 * menubar, the toolbar and the client area, which is represented by
653 * m_wxwindow.
654 * this hurts in the eye, but I don't want to call SetSize()
655 * because I don't want to call any non-native functions here. */
656
657 if (m_frameMenuBar)
658 {
659 int xx = m_miniEdge;
660 int yy = m_miniEdge + m_miniTitle;
661 int ww = m_width - 2*m_miniEdge;
662 int hh = wxMENU_HEIGHT;
663 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
664 m_frameMenuBar->m_x = xx;
665 m_frameMenuBar->m_y = yy;
666 m_frameMenuBar->m_width = ww;
667 m_frameMenuBar->m_height = hh;
668
669 gtk_myfixed_move( GTK_MYFIXED(m_mainWidget), m_frameMenuBar->m_widget, xx, yy );
670
671 // m_frameMenuBar->m_widget->requisition.width = ww;
672 // m_frameMenuBar->m_widget->requisition.height = hh;
673 gtk_widget_set_usize( m_frameMenuBar->m_widget, ww, hh );
674
675 client_area_y_offset += hh;
676 }
677
678 if (m_frameToolBar)
679 {
680 int xx = m_miniEdge;
681 int yy = m_miniEdge + m_miniTitle;
682 if (m_frameMenuBar)
683 {
684 if (!m_menuBarDetached)
685 yy += wxMENU_HEIGHT;
686 else
687 yy += wxPLACE_HOLDER;
688 }
689 int ww = m_width - 2*m_miniEdge;
690 int hh = m_frameToolBar->m_height;
691 if (m_toolBarDetached) hh = wxPLACE_HOLDER;
692 m_frameToolBar->m_x = xx;
693 m_frameToolBar->m_y = yy;
694 /* m_frameToolBar->m_height = hh; don't change the toolbar's height */
695 m_frameToolBar->m_width = ww;
696
697 gtk_myfixed_move( GTK_MYFIXED(m_mainWidget), m_frameToolBar->m_widget, xx, yy );
698
699 // m_frameToolBar->m_widget->requisition.width = ww;
700 // m_frameToolBar->m_widget->requisition.height = hh;
701 gtk_widget_set_usize( m_frameToolBar->m_widget, ww, hh );
702
703 client_area_y_offset += hh;
704 }
705
706 int client_x = m_miniEdge;
707 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
708 gtk_myfixed_move( GTK_MYFIXED(m_mainWidget), m_wxwindow, client_x, client_y );
709
710 int client_w = m_width - 2*m_miniEdge;
711 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
712 // m_wxwindow->requisition.width = client_w;
713 // m_wxwindow->requisition.height = client_h;
714 gtk_widget_set_usize( m_wxwindow, client_w, client_h );
715
716 }
717 else
718 {
719 /* if there is no m_mainWidget between m_widget and m_wxwindow there
720 is no need to set the size or position of m_wxwindow. */
721 }
722
723 if (m_frameStatusBar)
724 {
725 int xx = 0 + m_miniEdge;
726 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
727 int ww = m_width - 2*m_miniEdge;
728 int hh = wxSTATUS_HEIGHT;
729
730 m_frameStatusBar->m_x = xx;
731 m_frameStatusBar->m_y = yy;
732 m_frameStatusBar->m_width = ww;
733 m_frameStatusBar->m_height = hh;
734
735 gtk_myfixed_move( GTK_MYFIXED(m_wxwindow), m_frameStatusBar->m_widget, xx, yy );
736
737 // m_frameStatusBar->m_widget->requisition.width = ww;
738 // m_frameStatusBar->m_widget->requisition.height = hh;
739 gtk_widget_set_usize( m_frameStatusBar->m_widget, ww, hh );
740 }
741
742 /* we actually set the size of a frame here and no-where else */
743 gtk_widget_set_usize( m_widget, m_width, m_height );
744
745 m_sizeSet = TRUE;
746
747 /* send size event to frame */
748 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
749 event.SetEventObject( this );
750 GetEventHandler()->ProcessEvent( event );
751
752 /* send size event to status bar */
753 if (m_frameStatusBar)
754 {
755 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
756 event2.SetEventObject( m_frameStatusBar );
757 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
758 }
759
760 m_resizing = FALSE;
761 }
762
763 void wxFrame::OnInternalIdle()
764 {
765 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
766 GtkOnSize( m_x, m_y, m_width, m_height );
767
768 DoMenuUpdates();
769 }
770
771 void wxFrame::OnCloseWindow( wxCloseEvent& event )
772 {
773 Destroy();
774 }
775
776 void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) )
777 {
778 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
779
780 if (GetAutoLayout())
781 {
782 Layout();
783 }
784 else
785 {
786 /* do we have exactly one child? */
787 wxWindow *child = (wxWindow *)NULL;
788 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
789 {
790 wxWindow *win = (wxWindow *)node->Data();
791 if ( !wxIS_KIND_OF(win,wxFrame) && !wxIS_KIND_OF(win,wxDialog) )
792 {
793 if (child)
794 {
795 /* it's the second one: do nothing */
796 return;
797 }
798
799 child = win;
800 }
801 }
802
803 /* no children at all? */
804 if (child)
805 {
806 /* yes: set it's size to fill all the frame */
807 int client_x, client_y;
808 GetClientSize( &client_x, &client_y );
809 child->SetSize( 1, 1, client_x-2, client_y-2 );
810 }
811 }
812 }
813
814 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
815 {
816 menu->SetInvokingWindow( win );
817
818 #if (GTK_MINOR_VERSION > 0)
819 /* support for native hot keys */
820 gtk_accel_group_attach( menu->m_accel, GTK_OBJECT(win->m_widget));
821 #endif
822
823 wxNode *node = menu->GetItems().First();
824 while (node)
825 {
826 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
827 if (menuitem->IsSubMenu())
828 SetInvokingWindow( menuitem->GetSubMenu(), win );
829 node = node->Next();
830 }
831 }
832
833 void wxFrame::SetMenuBar( wxMenuBar *menuBar )
834 {
835 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
836 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
837
838 m_frameMenuBar = menuBar;
839
840 if (m_frameMenuBar)
841 {
842 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
843 /* support for native key accelerators indicated by underscroes */
844 gtk_accel_group_attach( m_frameMenuBar->m_accel, GTK_OBJECT(m_widget));
845 #endif
846
847 wxNode *node = m_frameMenuBar->GetMenus().First();
848 while (node)
849 {
850 wxMenu *menu = (wxMenu*)node->Data();
851 SetInvokingWindow( menu, this );
852 node = node->Next();
853 }
854
855 if (m_frameMenuBar->m_parent != this)
856 {
857 m_frameMenuBar->m_parent = this;
858 gtk_myfixed_put( GTK_MYFIXED(m_mainWidget),
859 m_frameMenuBar->m_widget, m_frameMenuBar->m_x, m_frameMenuBar->m_y );
860
861 if (menuBar->m_windowStyle & wxMB_DOCKABLE)
862 {
863 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
864 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
865
866 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
867 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
868 }
869 }
870 }
871
872 /* resize window in OnInternalIdle */
873 m_sizeSet = FALSE;
874 }
875
876 wxMenuBar *wxFrame::GetMenuBar() const
877 {
878 return m_frameMenuBar;
879 }
880
881 void wxFrame::OnMenuHighlight(wxMenuEvent& event)
882 {
883 if (GetStatusBar())
884 {
885 // if no help string found, we will clear the status bar text
886 wxString helpString;
887
888 int menuId = event.GetMenuId();
889 if ( menuId != -1 )
890 {
891 wxMenuBar *menuBar = GetMenuBar();
892 if (menuBar)
893 {
894 helpString = menuBar->GetHelpString(menuId);
895 }
896 }
897
898 SetStatusText(helpString);
899 }
900 }
901
902 wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
903 {
904 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
905
906 wxCHECK_MSG( m_frameToolBar == NULL, FALSE, _T("recreating toolbar in wxFrame") );
907
908 m_frameToolBar = OnCreateToolBar( style, id, name );
909
910 GetChildren().DeleteObject( m_frameToolBar );
911
912 m_sizeSet = FALSE;
913
914 return m_frameToolBar;
915 }
916
917 wxToolBar* wxFrame::OnCreateToolBar( long style, wxWindowID id, const wxString& name )
918 {
919 return new wxToolBar( this, id, wxDefaultPosition, wxDefaultSize, style, name );
920 }
921
922 wxToolBar *wxFrame::GetToolBar() const
923 {
924 return m_frameToolBar;
925 }
926
927 wxStatusBar* wxFrame::CreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
928 {
929 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
930
931 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE, _T("recreating status bar in wxFrame") );
932
933 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
934
935 m_sizeSet = FALSE;
936
937 return m_frameStatusBar;
938 }
939
940 wxStatusBar *wxFrame::OnCreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
941 {
942 wxStatusBar *statusBar = (wxStatusBar *) NULL;
943
944 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20), style, name);
945
946 // Set the height according to the font and the border size
947 wxClientDC dc(statusBar);
948 dc.SetFont( statusBar->GetFont() );
949
950 long x, y;
951 dc.GetTextExtent( "X", &x, &y );
952
953 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
954
955 statusBar->SetSize( -1, -1, 100, height );
956
957 statusBar->SetFieldsCount( number );
958 return statusBar;
959 }
960
961 void wxFrame::Command( int id )
962 {
963 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
964 commandEvent.SetInt( id );
965 commandEvent.SetEventObject( this );
966
967 wxMenuBar *bar = GetMenuBar();
968 if (!bar) return;
969
970 wxMenuItem *item = bar->FindItemForId(id) ;
971 if (item && item->IsCheckable())
972 {
973 bar->Check(id,!bar->Checked(id)) ;
974 }
975
976 wxEvtHandler* evtHandler = GetEventHandler();
977
978 evtHandler->ProcessEvent(commandEvent);
979 }
980
981 void wxFrame::SetStatusText(const wxString& text, int number)
982 {
983 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
984
985 wxCHECK_RET( m_frameStatusBar != NULL, _T("no statusbar to set text for") );
986
987 m_frameStatusBar->SetStatusText(text, number);
988 }
989
990 void wxFrame::SetStatusWidths(int n, const int widths_field[] )
991 {
992 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
993
994 wxCHECK_RET( m_frameStatusBar != NULL, _T("no statusbar to set widths for") );
995
996 m_frameStatusBar->SetStatusWidths(n, widths_field);
997 }
998
999 wxStatusBar *wxFrame::GetStatusBar() const
1000 {
1001 return m_frameStatusBar;
1002 }
1003
1004 void wxFrame::SetTitle( const wxString &title )
1005 {
1006 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
1007
1008 m_title = title;
1009 if (m_title.IsNull()) m_title = _T("");
1010 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
1011 }
1012
1013 void wxFrame::SetIcon( const wxIcon &icon )
1014 {
1015 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
1016
1017 m_icon = icon;
1018 if (!icon.Ok()) return;
1019
1020 if (!m_widget->window) return;
1021
1022 wxMask *mask = icon.GetMask();
1023 GdkBitmap *bm = (GdkBitmap *) NULL;
1024 if (mask) bm = mask->GetBitmap();
1025
1026 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
1027 }
1028