1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/frame.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
17 #include "wx/toolbar.h"
18 #include "wx/statusbr.h"
22 #include "wx/gtk/win_gtk.h"
24 // ----------------------------------------------------------------------------
26 // ----------------------------------------------------------------------------
28 static const int wxSTATUS_HEIGHT
= 25;
29 static const int wxPLACE_HOLDER
= 0;
31 // ----------------------------------------------------------------------------
33 // ----------------------------------------------------------------------------
35 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxTopLevelWindow
)
37 // ============================================================================
39 // ============================================================================
41 // ----------------------------------------------------------------------------
43 // ----------------------------------------------------------------------------
45 #if wxUSE_MENUS_NATIVE
47 //-----------------------------------------------------------------------------
48 // "child_attached" of menu bar
49 //-----------------------------------------------------------------------------
52 static void gtk_menu_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
54 if (!win
->m_hasVMT
) return;
56 win
->m_menuBarDetached
= false;
61 //-----------------------------------------------------------------------------
62 // "child_detached" of menu bar
63 //-----------------------------------------------------------------------------
66 static void gtk_menu_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
68 if (!win
->m_hasVMT
) return;
70 // Raise the client area area
71 gdk_window_raise( win
->m_wxwindow
->window
);
73 win
->m_menuBarDetached
= true;
78 #endif // wxUSE_MENUS_NATIVE
81 //-----------------------------------------------------------------------------
82 // "child_attached" of tool bar
83 //-----------------------------------------------------------------------------
86 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
88 if (!win
->m_hasVMT
) return;
90 win
->m_toolBarDetached
= false;
95 //-----------------------------------------------------------------------------
96 // "child_detached" of tool bar
97 //-----------------------------------------------------------------------------
100 static void gtk_toolbar_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
102 if (!win
->m_hasVMT
) return;
104 // Raise the client area area
105 gdk_window_raise( win
->m_wxwindow
->window
);
107 win
->m_toolBarDetached
= true;
108 win
->GtkUpdateSize();
111 #endif // wxUSE_TOOLBAR
114 // ----------------------------------------------------------------------------
116 // ----------------------------------------------------------------------------
118 //-----------------------------------------------------------------------------
119 // InsertChild for wxFrame
120 //-----------------------------------------------------------------------------
122 /* Callback for wxFrame. This very strange beast has to be used because
123 * C++ has no virtual methods in a constructor. We have to emulate a
124 * virtual function here as wxWidgets requires different ways to insert
125 * a child in container classes. */
127 static void wxInsertChildInFrame( wxFrame
* parent
, wxWindow
* child
)
129 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
131 if (!parent
->m_insertInClientArea
)
133 // These are outside the client area
134 wxFrame
* frame
= (wxFrame
*) parent
;
135 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
142 #if wxUSE_TOOLBAR_NATIVE
143 // We connect to these events for recalculating the client area
144 // space when the toolbar is floating
145 if (wxIS_KIND_OF(child
,wxToolBar
))
147 wxToolBar
*toolBar
= (wxToolBar
*) child
;
148 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
150 g_signal_connect (toolBar
->m_widget
, "child_attached",
151 G_CALLBACK (gtk_toolbar_attached_callback
),
153 g_signal_connect (toolBar
->m_widget
, "child_detached",
154 G_CALLBACK (gtk_toolbar_detached_callback
),
158 #endif // wxUSE_TOOLBAR
162 // These are inside the client area
163 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
172 // ----------------------------------------------------------------------------
174 // ----------------------------------------------------------------------------
178 m_menuBarDetached
= false;
179 m_toolBarDetached
= false;
183 bool wxFrame::Create( wxWindow
*parent
,
185 const wxString
& title
,
187 const wxSize
& sizeOrig
,
189 const wxString
&name
)
191 bool rt
= wxTopLevelWindow::Create(parent
, id
, title
, pos
, sizeOrig
,
193 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
200 m_isBeingDeleted
= true;
204 // ----------------------------------------------------------------------------
205 // overridden wxWindow methods
206 // ----------------------------------------------------------------------------
208 void wxFrame::DoGetClientSize( int *width
, int *height
) const
210 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
212 wxTopLevelWindow::DoGetClientSize( width
, height
);
216 #if wxUSE_MENUS_NATIVE
218 if (m_frameMenuBar
&& !(m_fsIsShowing
&& (m_fsSaveFlag
& wxFULLSCREEN_NOMENUBAR
) != 0))
220 if (!m_menuBarDetached
)
221 (*height
) -= m_menuBarHeight
;
223 (*height
) -= wxPLACE_HOLDER
;
225 #endif // wxUSE_MENUS_NATIVE
229 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown() &&
230 !(m_fsIsShowing
&& (m_fsSaveFlag
& wxFULLSCREEN_NOSTATUSBAR
) != 0))
231 (*height
) -= wxSTATUS_HEIGHT
;
232 #endif // wxUSE_STATUSBAR
237 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
239 if (m_toolBarDetached
)
242 *height
-= wxPLACE_HOLDER
;
247 m_frameToolBar
->GetSize( &x
, &y
);
248 if ( m_frameToolBar
->IsVertical() )
260 #endif // wxUSE_TOOLBAR
262 if (width
!= NULL
&& *width
< 0)
264 if (height
!= NULL
&& *height
< 0)
268 void wxFrame::DoSetClientSize( int width
, int height
)
270 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
272 #if wxUSE_MENUS_NATIVE
274 if (m_frameMenuBar
&& !(m_fsIsShowing
&& (m_fsSaveFlag
& wxFULLSCREEN_NOMENUBAR
) != 0))
276 if (!m_menuBarDetached
)
277 height
+= m_menuBarHeight
;
279 height
+= wxPLACE_HOLDER
;
281 #endif // wxUSE_MENUS_NATIVE
285 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown() &&
286 !(m_fsIsShowing
&& (m_fsSaveFlag
& wxFULLSCREEN_NOSTATUSBAR
) != 0))
287 height
+= wxSTATUS_HEIGHT
;
292 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
294 if (m_toolBarDetached
)
296 height
+= wxPLACE_HOLDER
;
301 m_frameToolBar
->GetSize( &x
, &y
);
302 if ( m_frameToolBar
->IsVertical() )
314 wxTopLevelWindow::DoSetClientSize( width
, height
);
317 void wxFrame::GtkOnSize()
320 if (m_resizing
) return;
323 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
324 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
326 // space occupied by m_frameToolBar and m_frameMenuBar
327 int client_area_x_offset
= 0,
328 client_area_y_offset
= 0;
330 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
331 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
332 set in wxFrame::Create so it is used to check what kind of frame we
333 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
334 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
335 importantly) m_mainWidget */
337 int minWidth
= GetMinWidth(),
338 minHeight
= GetMinHeight(),
339 maxWidth
= GetMaxWidth(),
340 maxHeight
= GetMaxHeight();
342 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
343 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
344 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
345 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
350 // Rewrite this terrible code to using GtkVBox
352 // m_mainWidget holds the menubar, the toolbar and the client
353 // area, which is represented by m_wxwindow.
355 #if wxUSE_MENUS_NATIVE
356 if (m_frameMenuBar
&& !(m_fsIsShowing
&& (m_fsSaveFlag
& wxFULLSCREEN_NOMENUBAR
) != 0))
358 if (!GTK_WIDGET_VISIBLE(m_frameMenuBar
->m_widget
))
359 gtk_widget_show( m_frameMenuBar
->m_widget
);
361 int yy
= m_miniEdge
+ m_miniTitle
;
362 int ww
= m_width
- 2*m_miniEdge
;
365 int hh
= m_menuBarHeight
;
366 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
367 m_frameMenuBar
->m_x
= xx
;
368 m_frameMenuBar
->m_y
= yy
;
369 m_frameMenuBar
->m_width
= ww
;
370 m_frameMenuBar
->m_height
= hh
;
371 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
372 m_frameMenuBar
->m_widget
,
374 client_area_y_offset
+= hh
;
380 if (GTK_WIDGET_VISIBLE(m_frameMenuBar
->m_widget
))
381 gtk_widget_hide( m_frameMenuBar
->m_widget
);
384 #endif // wxUSE_MENUS_NATIVE
387 if ((m_frameToolBar
) && m_frameToolBar
->IsShown() &&
388 (m_frameToolBar
->m_widget
->parent
== m_mainWidget
))
391 int yy
= m_miniEdge
+ m_miniTitle
;
392 #if wxUSE_MENUS_NATIVE
395 if (!m_menuBarDetached
)
396 yy
+= m_menuBarHeight
;
398 yy
+= wxPLACE_HOLDER
;
400 #endif // wxUSE_MENUS_NATIVE
402 m_frameToolBar
->m_x
= xx
;
403 m_frameToolBar
->m_y
= yy
;
405 // don't change the toolbar's reported height/width
407 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
409 ww
= m_toolBarDetached
? wxPLACE_HOLDER
410 : m_frameToolBar
->m_width
;
411 hh
= m_height
- 2*m_miniEdge
;
413 client_area_x_offset
+= ww
;
415 else if( m_frameToolBar
->HasFlag(wxTB_RIGHT
) )
418 ww
= m_toolBarDetached
? wxPLACE_HOLDER
419 : m_frameToolBar
->m_width
;
420 xx
= GetClientSize().x
- 1;
421 hh
= m_height
- 2*m_miniEdge
;
426 else if( m_frameToolBar
->GetWindowStyle() & wxTB_BOTTOM
)
429 yy
= GetClientSize().y
;
430 #if wxUSE_MENUS_NATIVE
431 yy
+= m_menuBarHeight
;
432 #endif // wxUSE_MENU_NATIVE
433 m_frameToolBar
->m_x
= xx
;
434 m_frameToolBar
->m_y
= yy
;
435 ww
= m_width
- 2*m_miniEdge
;
436 hh
= m_toolBarDetached
? wxPLACE_HOLDER
437 : m_frameToolBar
->m_height
;
441 ww
= m_width
- 2*m_miniEdge
;
442 hh
= m_toolBarDetached
? wxPLACE_HOLDER
443 : m_frameToolBar
->m_height
;
445 client_area_y_offset
+= hh
;
452 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
453 m_frameToolBar
->m_widget
,
456 #endif // wxUSE_TOOLBAR
458 int client_x
= client_area_x_offset
+ m_miniEdge
;
459 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
460 int client_w
= m_width
- client_area_x_offset
- 2*m_miniEdge
;
461 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
466 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
468 client_x
, client_y
, client_w
, client_h
);
472 // If there is no m_mainWidget between m_widget and m_wxwindow there
473 // is no need to set the size or position of m_wxwindow.
477 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown() &&
478 !(m_fsIsShowing
&& (m_fsSaveFlag
& wxFULLSCREEN_NOSTATUSBAR
) != 0))
480 if (!GTK_WIDGET_VISIBLE(m_frameStatusBar
->m_widget
))
481 gtk_widget_show( m_frameStatusBar
->m_widget
);
483 int xx
= 0 + m_miniEdge
;
484 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
485 int ww
= m_width
- 2*m_miniEdge
;
488 int hh
= wxSTATUS_HEIGHT
;
489 m_frameStatusBar
->m_x
= xx
;
490 m_frameStatusBar
->m_y
= yy
;
491 m_frameStatusBar
->m_width
= ww
;
492 m_frameStatusBar
->m_height
= hh
;
493 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
),
494 m_frameStatusBar
->m_widget
,
499 if (m_frameStatusBar
)
501 if (GTK_WIDGET_VISIBLE(m_frameStatusBar
->m_widget
))
502 gtk_widget_hide( m_frameStatusBar
->m_widget
);
505 #endif // wxUSE_STATUSBAR
509 // send size event to frame
510 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
511 event
.SetEventObject( this );
512 GetEventHandler()->ProcessEvent( event
);
515 // send size event to status bar
516 if (m_frameStatusBar
)
518 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
519 event2
.SetEventObject( m_frameStatusBar
);
520 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
522 #endif // wxUSE_STATUSBAR
527 void wxFrame::OnInternalIdle()
529 wxFrameBase::OnInternalIdle();
531 #if wxUSE_MENUS_NATIVE
532 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
533 #endif // wxUSE_MENUS_NATIVE
535 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
538 if (m_frameStatusBar
)
540 m_frameStatusBar
->OnInternalIdle();
542 // There may be controls in the status bar that
543 // need to be updated
544 for ( wxWindowList::compatibility_iterator node
= m_frameStatusBar
->GetChildren().GetFirst();
546 node
= node
->GetNext() )
548 wxWindow
*child
= node
->GetData();
549 child
->OnInternalIdle();
555 // ----------------------------------------------------------------------------
556 // menu/tool/status bar stuff
557 // ----------------------------------------------------------------------------
559 #if wxUSE_MENUS_NATIVE
561 void wxFrame::DetachMenuBar()
563 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
564 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
566 if ( m_frameMenuBar
)
568 m_frameMenuBar
->UnsetInvokingWindow( this );
570 if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
572 g_signal_handlers_disconnect_by_func (m_frameMenuBar
->m_widget
,
573 (gpointer
) gtk_menu_attached_callback
,
576 g_signal_handlers_disconnect_by_func (m_frameMenuBar
->m_widget
,
577 (gpointer
) gtk_menu_detached_callback
,
581 gtk_widget_ref( m_frameMenuBar
->m_widget
);
583 gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget
);
586 wxFrameBase::DetachMenuBar();
589 void wxFrame::AttachMenuBar( wxMenuBar
*menuBar
)
591 wxFrameBase::AttachMenuBar(menuBar
);
595 m_frameMenuBar
->SetInvokingWindow( this );
597 m_frameMenuBar
->SetParent(this);
598 gtk_pizza_put( GTK_PIZZA(m_mainWidget
),
599 m_frameMenuBar
->m_widget
,
602 m_frameMenuBar
->m_width
,
603 m_frameMenuBar
->m_height
);
605 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
607 g_signal_connect (menuBar
->m_widget
, "child_attached",
608 G_CALLBACK (gtk_menu_attached_callback
),
610 g_signal_connect (menuBar
->m_widget
, "child_detached",
611 G_CALLBACK (gtk_menu_detached_callback
),
615 gtk_widget_show( m_frameMenuBar
->m_widget
);
622 GtkUpdateSize(); // resize window in OnInternalIdle
626 void wxFrame::UpdateMenuBarSize()
630 // this is called after Remove with a NULL m_frameMenuBar
631 if ( m_frameMenuBar
)
634 gtk_widget_ensure_style(m_frameMenuBar
->m_widget
);
635 // have to call class method directly because
636 // "size_request" signal is overridden by wx
637 GTK_WIDGET_GET_CLASS(m_frameMenuBar
->m_widget
)->size_request(
638 m_frameMenuBar
->m_widget
, &req
);
640 m_menuBarHeight
= req
.height
;
643 // resize window in OnInternalIdle
647 #endif // wxUSE_MENUS_NATIVE
651 wxToolBar
* wxFrame::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
653 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
655 m_insertInClientArea
= false;
657 m_frameToolBar
= wxFrameBase::CreateToolBar( style
, id
, name
);
659 m_insertInClientArea
= true;
663 return m_frameToolBar
;
666 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
668 bool hadTbar
= m_frameToolBar
!= NULL
;
670 wxFrameBase::SetToolBar(toolbar
);
672 if ( m_frameToolBar
)
674 // insert into toolbar area if not already there
675 if ((m_frameToolBar
->m_widget
->parent
) &&
676 (m_frameToolBar
->m_widget
->parent
!= m_mainWidget
))
678 GetChildren().DeleteObject( m_frameToolBar
);
680 gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget
);
684 else // toolbar unset
686 // still need to update size if it had been there before
694 #endif // wxUSE_TOOLBAR
698 wxStatusBar
* wxFrame::CreateStatusBar(int number
,
701 const wxString
& name
)
703 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
705 // because it will change when toolbar is added
708 return wxFrameBase::CreateStatusBar( number
, style
, id
, name
);
711 void wxFrame::SetStatusBar(wxStatusBar
*statbar
)
713 bool hadStatBar
= m_frameStatusBar
!= NULL
;
715 wxFrameBase::SetStatusBar(statbar
);
717 if (hadStatBar
&& !m_frameStatusBar
)
721 void wxFrame::PositionStatusBar()
723 if ( !m_frameStatusBar
)
728 #endif // wxUSE_STATUSBAR