1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
19 #pragma implementation "frame.h"
24 #include "wx/dialog.h"
25 #include "wx/control.h"
29 #include "wx/toolbar.h"
32 #include "wx/statusbr.h"
34 #include "wx/dcclient.h"
37 #include "wx/gtk/private.h"
39 #include <gdk/gdkkeysyms.h>
42 #include "wx/gtk/win_gtk.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 const int wxSTATUS_HEIGHT
= 25;
49 const int wxPLACE_HOLDER
= 0;
51 // ----------------------------------------------------------------------------
53 // ----------------------------------------------------------------------------
55 extern void wxapp_install_idle_handler();
57 extern int g_openDialogs
;
59 // ----------------------------------------------------------------------------
61 // ----------------------------------------------------------------------------
63 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxTopLevelWindow
)
65 // ============================================================================
67 // ============================================================================
69 // ----------------------------------------------------------------------------
71 // ----------------------------------------------------------------------------
73 #if wxUSE_MENUS_NATIVE
75 //-----------------------------------------------------------------------------
76 // "child_attached" of menu bar
77 //-----------------------------------------------------------------------------
79 static void gtk_menu_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
81 if (!win
->m_hasVMT
) return;
83 win
->m_menuBarDetached
= FALSE
;
87 //-----------------------------------------------------------------------------
88 // "child_detached" of menu bar
89 //-----------------------------------------------------------------------------
91 static void gtk_menu_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
94 wxapp_install_idle_handler();
96 if (!win
->m_hasVMT
) return;
98 // Raise the client area area
99 gdk_window_raise( win
->m_wxwindow
->window
);
101 win
->m_menuBarDetached
= TRUE
;
102 win
->GtkUpdateSize();
105 #endif // wxUSE_MENUS_NATIVE
108 //-----------------------------------------------------------------------------
109 // "child_attached" of tool bar
110 //-----------------------------------------------------------------------------
112 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
114 if (!win
->m_hasVMT
) return;
116 win
->m_toolBarDetached
= FALSE
;
117 win
->GtkUpdateSize();
120 //-----------------------------------------------------------------------------
121 // "child_detached" of tool bar
122 //-----------------------------------------------------------------------------
124 static void gtk_toolbar_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
127 wxapp_install_idle_handler();
129 if (!win
->m_hasVMT
) return;
131 // Raise the client area area
132 gdk_window_raise( win
->m_wxwindow
->window
);
134 win
->m_toolBarDetached
= TRUE
;
135 win
->GtkUpdateSize();
137 #endif // wxUSE_TOOLBAR
140 // ----------------------------------------------------------------------------
142 // ----------------------------------------------------------------------------
144 //-----------------------------------------------------------------------------
145 // InsertChild for wxFrame
146 //-----------------------------------------------------------------------------
148 /* Callback for wxFrame. This very strange beast has to be used because
149 * C++ has no virtual methods in a constructor. We have to emulate a
150 * virtual function here as wxWindows requires different ways to insert
151 * a child in container classes. */
153 static void wxInsertChildInFrame( wxFrame
* parent
, wxWindow
* child
)
155 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
157 if (!parent
->m_insertInClientArea
)
159 // These are outside the client area
160 wxFrame
* frame
= (wxFrame
*) parent
;
161 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
162 GTK_WIDGET(child
->m_widget
),
168 #if wxUSE_TOOLBAR_NATIVE
169 // We connect to these events for recalculating the client area
170 // space when the toolbar is floating
171 if (wxIS_KIND_OF(child
,wxToolBar
))
173 wxToolBar
*toolBar
= (wxToolBar
*) child
;
174 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
176 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_attached",
177 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback
), (gpointer
)parent
);
179 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_detached",
180 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback
), (gpointer
)parent
);
183 #endif // wxUSE_TOOLBAR
187 // These are inside the client area
188 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
189 GTK_WIDGET(child
->m_widget
),
196 // Resize on OnInternalIdle
197 parent
->GtkUpdateSize();
200 // ----------------------------------------------------------------------------
202 // ----------------------------------------------------------------------------
206 m_menuBarDetached
= FALSE
;
207 m_toolBarDetached
= FALSE
;
211 bool wxFrame::Create( wxWindow
*parent
,
213 const wxString
& title
,
215 const wxSize
& sizeOrig
,
217 const wxString
&name
)
219 bool rt
= wxTopLevelWindow::Create(parent
, id
, title
, pos
, sizeOrig
,
221 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
228 m_isBeingDeleted
= TRUE
;
232 // ----------------------------------------------------------------------------
233 // overridden wxWindow methods
234 // ----------------------------------------------------------------------------
236 void wxFrame::DoGetClientSize( int *width
, int *height
) const
238 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
240 wxTopLevelWindow::DoGetClientSize( width
, height
);
244 #if wxUSE_MENUS_NATIVE
248 if (!m_menuBarDetached
)
249 (*height
) -= m_menuBarHeight
;
251 (*height
) -= wxPLACE_HOLDER
;
253 #endif // wxUSE_MENUS_NATIVE
257 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
258 (*height
) -= wxSTATUS_HEIGHT
;
259 #endif // wxUSE_STATUSBAR
263 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
265 if (m_toolBarDetached
)
267 *height
-= wxPLACE_HOLDER
;
272 m_frameToolBar
->GetSize( &x
, &y
);
273 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
283 #endif // wxUSE_TOOLBAR
287 void wxFrame::DoSetClientSize( int width
, int height
)
289 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
291 #if wxUSE_MENUS_NATIVE
295 if (!m_menuBarDetached
)
296 height
+= m_menuBarHeight
;
298 height
+= wxPLACE_HOLDER
;
300 #endif // wxUSE_MENUS_NATIVE
304 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) height
+= wxSTATUS_HEIGHT
;
309 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
311 if (m_toolBarDetached
)
313 height
+= wxPLACE_HOLDER
;
318 m_frameToolBar
->GetSize( &x
, &y
);
319 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
331 wxTopLevelWindow::DoSetClientSize( width
, height
);
334 void wxFrame::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
335 int width
, int height
)
337 // due to a bug in gtk, x,y are always 0
342 if (m_resizing
) return;
345 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
346 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
351 // space occupied by m_frameToolBar and m_frameMenuBar
352 int client_area_x_offset
= 0,
353 client_area_y_offset
= 0;
355 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
356 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
357 set in wxFrame::Create so it is used to check what kind of frame we
358 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
359 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
360 importantly) m_mainWidget */
362 int minWidth
= GetMinWidth(),
363 minHeight
= GetMinHeight(),
364 maxWidth
= GetMaxWidth(),
365 maxHeight
= GetMaxHeight();
367 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
368 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
369 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
370 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
375 gint flag
= 0; // GDK_HINT_POS;
376 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
377 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
379 geom
.min_width
= minWidth
;
380 geom
.min_height
= minHeight
;
381 geom
.max_width
= maxWidth
;
382 geom
.max_height
= maxHeight
;
383 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
386 (GdkWindowHints
) flag
);
388 // I revert back to wxGTK's original behaviour. m_mainWidget holds
389 // the menubar, the toolbar and the client area, which is represented
391 // This hurts in the eye, but I don't want to call SetSize()
392 // because I don't want to call any non-native functions here.
394 #if wxUSE_MENUS_NATIVE
398 int yy
= m_miniEdge
+ m_miniTitle
;
399 int ww
= m_width
- 2*m_miniEdge
;
400 int hh
= m_menuBarHeight
;
401 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
402 m_frameMenuBar
->m_x
= xx
;
403 m_frameMenuBar
->m_y
= yy
;
404 m_frameMenuBar
->m_width
= ww
;
405 m_frameMenuBar
->m_height
= hh
;
406 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
407 m_frameMenuBar
->m_widget
,
409 client_area_y_offset
+= hh
;
411 #endif // wxUSE_MENUS_NATIVE
414 if ((m_frameToolBar
) && m_frameToolBar
->IsShown() &&
415 (m_frameToolBar
->m_widget
->parent
== m_mainWidget
))
418 int yy
= m_miniEdge
+ m_miniTitle
;
419 #if wxUSE_MENUS_NATIVE
422 if (!m_menuBarDetached
)
423 yy
+= m_menuBarHeight
;
425 yy
+= wxPLACE_HOLDER
;
427 #endif // wxUSE_MENUS_NATIVE
429 m_frameToolBar
->m_x
= xx
;
430 m_frameToolBar
->m_y
= yy
;
432 // don't change the toolbar's reported height/width
434 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
436 ww
= m_toolBarDetached
? wxPLACE_HOLDER
437 : m_frameToolBar
->m_width
;
438 hh
= m_height
- 2*m_miniEdge
;
440 client_area_x_offset
+= ww
;
444 ww
= m_width
- 2*m_miniEdge
;
445 hh
= m_toolBarDetached
? wxPLACE_HOLDER
446 : m_frameToolBar
->m_height
;
448 client_area_y_offset
+= hh
;
451 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
452 m_frameToolBar
->m_widget
,
455 #endif // wxUSE_TOOLBAR
457 int client_x
= client_area_x_offset
+ m_miniEdge
;
458 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
459 int client_w
= m_width
- client_area_x_offset
- 2*m_miniEdge
;
460 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
461 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
463 client_x
, client_y
, client_w
, client_h
);
467 // If there is no m_mainWidget between m_widget and m_wxwindow there
468 // is no need to set the size or position of m_wxwindow.
472 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
474 int xx
= 0 + m_miniEdge
;
475 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
476 int ww
= m_width
- 2*m_miniEdge
;
477 int hh
= wxSTATUS_HEIGHT
;
478 m_frameStatusBar
->m_x
= xx
;
479 m_frameStatusBar
->m_y
= yy
;
480 m_frameStatusBar
->m_width
= ww
;
481 m_frameStatusBar
->m_height
= hh
;
482 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
),
483 m_frameStatusBar
->m_widget
,
485 gtk_widget_draw( m_frameStatusBar
->m_widget
, (GdkRectangle
*) NULL
);
487 #endif // wxUSE_STATUSBAR
491 // send size event to frame
492 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
493 event
.SetEventObject( this );
494 GetEventHandler()->ProcessEvent( event
);
497 // send size event to status bar
498 if (m_frameStatusBar
)
500 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
501 event2
.SetEventObject( m_frameStatusBar
);
502 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
504 #endif // wxUSE_STATUSBAR
509 void wxFrame::OnInternalIdle()
511 wxFrameBase::OnInternalIdle();
513 #if wxUSE_MENUS_NATIVE
514 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
515 #endif // wxUSE_MENUS_NATIVE
517 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
520 if (m_frameStatusBar
) m_frameStatusBar
->OnInternalIdle();
524 // ----------------------------------------------------------------------------
525 // menu/tool/status bar stuff
526 // ----------------------------------------------------------------------------
528 #if wxUSE_MENUS_NATIVE
530 void wxFrame::DetachMenuBar()
532 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
533 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
535 if ( m_frameMenuBar
)
537 m_frameMenuBar
->UnsetInvokingWindow( this );
539 if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
541 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
542 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
544 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
545 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
548 gtk_widget_ref( m_frameMenuBar
->m_widget
);
550 gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget
);
553 wxFrameBase::DetachMenuBar();
556 void wxFrame::AttachMenuBar( wxMenuBar
*menuBar
)
558 wxFrameBase::AttachMenuBar(menuBar
);
562 m_frameMenuBar
->SetInvokingWindow( this );
564 m_frameMenuBar
->SetParent(this);
565 gtk_pizza_put( GTK_PIZZA(m_mainWidget
),
566 m_frameMenuBar
->m_widget
,
569 m_frameMenuBar
->m_width
,
570 m_frameMenuBar
->m_height
);
572 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
574 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_attached",
575 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
577 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_detached",
578 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
581 m_frameMenuBar
->Show( TRUE
);
588 GtkUpdateSize(); // resize window in OnInternalIdle
592 void wxFrame::UpdateMenuBarSize()
594 wxASSERT_MSG( m_frameMenuBar
, _T("Updating non existant menubar?") );
601 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_frameMenuBar
->m_widget
) )->size_request
)
602 (m_frameMenuBar
->m_widget
, &req
);
604 m_menuBarHeight
= req
.height
;
606 // resize window in OnInternalIdle
611 #endif // wxUSE_MENUS_NATIVE
615 wxToolBar
* wxFrame::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
617 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
619 m_insertInClientArea
= FALSE
;
621 m_frameToolBar
= wxFrameBase::CreateToolBar( style
, id
, name
);
623 m_insertInClientArea
= TRUE
;
627 return m_frameToolBar
;
630 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
632 bool hadTbar
= m_frameToolBar
!= NULL
;
634 wxFrameBase::SetToolBar(toolbar
);
636 if ( m_frameToolBar
)
638 // insert into toolbar area if not already there
639 if ((m_frameToolBar
->m_widget
->parent
) &&
640 (m_frameToolBar
->m_widget
->parent
!= m_mainWidget
))
642 GetChildren().DeleteObject( m_frameToolBar
);
644 gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget
);
648 else // toolbar unset
650 // still need to update size if it had been there before
658 #endif // wxUSE_TOOLBAR
662 wxStatusBar
* wxFrame::CreateStatusBar(int number
,
665 const wxString
& name
)
667 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
669 // because it will change when toolbar is added
672 return wxFrameBase::CreateStatusBar( number
, style
, id
, name
);
675 void wxFrame::PositionStatusBar()
677 if ( !m_frameStatusBar
)
682 #endif // wxUSE_STATUSBAR