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 //-----------------------------------------------------------------------------
124 /* Callback for wxFrame. This very strange beast has to be used because
125 * C++ has no virtual methods in a constructor. We have to emulate a
126 * virtual function here as wxWidgets requires different ways to insert
127 * a child in container classes. */
129 static void wxInsertChildInFrame(wxWindow
* parent
, wxWindow
* child
)
131 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
133 // These are outside the client area
134 wxFrame
* frame
= wx_static_cast(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 if (child
->HasFlag(wxTB_DOCKABLE
))
149 g_signal_connect (child
->m_widget
, "child_attached",
150 G_CALLBACK (gtk_toolbar_attached_callback
),
152 g_signal_connect (child
->m_widget
, "child_detached",
153 G_CALLBACK (gtk_toolbar_detached_callback
),
157 #endif // wxUSE_TOOLBAR_NATIVE
160 #endif // wxUSE_TOOLBAR
162 // ----------------------------------------------------------------------------
164 // ----------------------------------------------------------------------------
168 m_menuBarDetached
= false;
169 m_toolBarDetached
= false;
174 bool wxFrame::Create( wxWindow
*parent
,
176 const wxString
& title
,
178 const wxSize
& sizeOrig
,
180 const wxString
&name
)
182 return wxFrameBase::Create(parent
, id
, title
, pos
, sizeOrig
, style
, name
);
187 m_isBeingDeleted
= true;
191 // ----------------------------------------------------------------------------
192 // overridden wxWindow methods
193 // ----------------------------------------------------------------------------
195 void wxFrame::DoGetClientSize( int *width
, int *height
) const
197 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
199 wxFrameBase::DoGetClientSize(width
, height
);
203 #if wxUSE_MENUS_NATIVE
205 if (HasVisibleMenubar() && !m_menuBarDetached
)
207 *height
-= m_menuBarHeight
;
209 #endif // wxUSE_MENUS_NATIVE
213 if (m_frameStatusBar
&& GTK_WIDGET_VISIBLE(m_frameStatusBar
->m_widget
))
214 *height
-= wxSTATUS_HEIGHT
;
215 #endif // wxUSE_STATUSBAR
220 if (m_frameToolBar
&&
221 GTK_WIDGET_VISIBLE(m_frameToolBar
->m_widget
) && !m_toolBarDetached
)
223 if (m_frameToolBar
->IsVertical())
226 *width
-= m_frameToolBar
->GetSize().x
;
231 *height
-= m_frameToolBar
->GetSize().y
;
234 #endif // wxUSE_TOOLBAR
236 if (width
!= NULL
&& *width
< 0)
238 if (height
!= NULL
&& *height
< 0)
242 bool wxFrame::ShowFullScreen(bool show
, long style
)
244 if (!wxFrameBase::ShowFullScreen(show
, style
))
247 wxWindow
* const bar
[] = {
264 const long fsNoBar
[] = {
265 wxFULLSCREEN_NOMENUBAR
, wxFULLSCREEN_NOTOOLBAR
, wxFULLSCREEN_NOSTATUSBAR
267 for (int i
= 0; i
< 3; i
++)
271 if (bar
[i
] && (style
& fsNoBar
[i
]))
273 if (bar
[i
]->IsShown())
276 style
&= ~fsNoBar
[i
];
281 if (bar
[i
] && (m_fsSaveFlag
& fsNoBar
[i
]))
286 m_fsSaveFlag
= style
;
291 void wxFrame::GtkOnSize()
294 if (m_resizing
) return;
297 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
298 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
300 // space occupied by m_frameToolBar and m_frameMenuBar
301 int client_area_x_offset
= 0,
302 client_area_y_offset
= 0;
304 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
305 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
306 set in wxFrame::Create so it is used to check what kind of frame we
307 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
308 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
309 importantly) m_mainWidget */
314 GTKDoGetSize(&width
, &height
);
319 // Rewrite this terrible code to using GtkVBox
321 // m_mainWidget holds the menubar, the toolbar and the client
322 // area, which is represented by m_wxwindow.
324 #if wxUSE_MENUS_NATIVE
325 int menubarHeight
= 0;
328 #if wxUSE_MENUS_NATIVE
329 if (HasVisibleMenubar())
332 int yy
= m_miniEdge
+ m_miniTitle
;
333 int ww
= width
- 2*m_miniEdge
;
336 menubarHeight
= m_menuBarHeight
;
337 if (m_menuBarDetached
) menubarHeight
= wxPLACE_HOLDER
;
338 m_frameMenuBar
->m_x
= xx
;
339 m_frameMenuBar
->m_y
= yy
;
340 m_frameMenuBar
->m_width
= ww
;
341 m_frameMenuBar
->m_height
= menubarHeight
;
342 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
343 m_frameMenuBar
->m_widget
,
344 xx
, yy
, ww
, menubarHeight
);
345 client_area_y_offset
+= menubarHeight
;
347 #endif // wxUSE_MENUS_NATIVE
350 if ((m_frameToolBar
) && m_frameToolBar
->IsShown() &&
351 (m_frameToolBar
->m_widget
->parent
== m_mainWidget
))
354 int yy
= m_miniEdge
+ m_miniTitle
355 #if wxUSE_MENUS_NATIVE
360 m_frameToolBar
->m_x
= xx
;
361 m_frameToolBar
->m_y
= yy
;
363 // don't change the toolbar's reported height/width
365 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
367 ww
= m_toolBarDetached
? wxPLACE_HOLDER
368 : m_frameToolBar
->m_width
;
369 hh
= height
- 2*m_miniEdge
;
371 client_area_x_offset
+= ww
;
373 else if( m_frameToolBar
->HasFlag(wxTB_RIGHT
) )
376 ww
= m_toolBarDetached
? wxPLACE_HOLDER
377 : m_frameToolBar
->m_width
;
378 xx
= GetClientSize().x
- 1;
379 hh
= height
- 2*m_miniEdge
;
384 else if( m_frameToolBar
->GetWindowStyle() & wxTB_BOTTOM
)
387 yy
= GetClientSize().y
;
388 #if wxUSE_MENUS_NATIVE
389 yy
+= m_menuBarHeight
;
390 #endif // wxUSE_MENUS_NATIVE
391 m_frameToolBar
->m_x
= xx
;
392 m_frameToolBar
->m_y
= yy
;
393 ww
= width
- 2*m_miniEdge
;
394 hh
= m_toolBarDetached
? wxPLACE_HOLDER
395 : m_frameToolBar
->m_height
;
399 ww
= width
- 2*m_miniEdge
;
400 hh
= m_toolBarDetached
? wxPLACE_HOLDER
401 : m_frameToolBar
->m_height
;
403 client_area_y_offset
+= hh
;
410 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
411 m_frameToolBar
->m_widget
,
414 #endif // wxUSE_TOOLBAR
416 int client_x
= client_area_x_offset
+ m_miniEdge
;
417 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
418 int client_w
= width
- client_area_x_offset
- 2*m_miniEdge
;
419 int client_h
= height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
424 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
426 client_x
, client_y
, client_w
, client_h
);
430 // If there is no m_mainWidget between m_widget and m_wxwindow there
431 // is no need to set the size or position of m_wxwindow.
435 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
437 int xx
= 0 + m_miniEdge
;
438 int yy
= height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
439 int ww
= width
- 2*m_miniEdge
;
442 int hh
= wxSTATUS_HEIGHT
;
443 m_frameStatusBar
->m_x
= xx
;
444 m_frameStatusBar
->m_y
= yy
;
445 m_frameStatusBar
->m_width
= ww
;
446 m_frameStatusBar
->m_height
= hh
;
447 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
),
448 m_frameStatusBar
->m_widget
,
451 #endif // wxUSE_STATUSBAR
455 // send size event to frame
456 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
457 event
.SetEventObject( this );
458 GetEventHandler()->ProcessEvent( event
);
461 // send size event to status bar
462 if (m_frameStatusBar
)
464 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
465 event2
.SetEventObject( m_frameStatusBar
);
466 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
468 #endif // wxUSE_STATUSBAR
473 void wxFrame::OnInternalIdle()
475 wxFrameBase::OnInternalIdle();
477 #if wxUSE_MENUS_NATIVE
478 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
479 #endif // wxUSE_MENUS_NATIVE
481 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
484 if (m_frameStatusBar
)
486 m_frameStatusBar
->OnInternalIdle();
488 // There may be controls in the status bar that
489 // need to be updated
490 for ( wxWindowList::compatibility_iterator node
= m_frameStatusBar
->GetChildren().GetFirst();
492 node
= node
->GetNext() )
494 wxWindow
*child
= node
->GetData();
495 child
->OnInternalIdle();
501 // ----------------------------------------------------------------------------
502 // menu/tool/status bar stuff
503 // ----------------------------------------------------------------------------
505 #if wxUSE_MENUS_NATIVE
507 void wxFrame::DetachMenuBar()
509 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
510 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
512 if ( m_frameMenuBar
)
514 m_frameMenuBar
->UnsetInvokingWindow( this );
516 if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
518 g_signal_handlers_disconnect_by_func (m_frameMenuBar
->m_widget
,
519 (gpointer
) gtk_menu_attached_callback
,
522 g_signal_handlers_disconnect_by_func (m_frameMenuBar
->m_widget
,
523 (gpointer
) gtk_menu_detached_callback
,
527 gtk_widget_ref( m_frameMenuBar
->m_widget
);
529 gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget
);
532 wxFrameBase::DetachMenuBar();
535 void wxFrame::AttachMenuBar( wxMenuBar
*menuBar
)
537 wxFrameBase::AttachMenuBar(menuBar
);
541 m_frameMenuBar
->SetInvokingWindow( this );
543 m_frameMenuBar
->SetParent(this);
544 gtk_pizza_put( GTK_PIZZA(m_mainWidget
),
545 m_frameMenuBar
->m_widget
,
548 m_frameMenuBar
->m_width
,
549 m_frameMenuBar
->m_height
);
551 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
553 g_signal_connect (menuBar
->m_widget
, "child_attached",
554 G_CALLBACK (gtk_menu_attached_callback
),
556 g_signal_connect (menuBar
->m_widget
, "child_detached",
557 G_CALLBACK (gtk_menu_detached_callback
),
561 gtk_widget_show( m_frameMenuBar
->m_widget
);
568 GtkUpdateSize(); // resize window in OnInternalIdle
572 void wxFrame::UpdateMenuBarSize()
576 // this is called after Remove with a NULL m_frameMenuBar
577 if ( m_frameMenuBar
)
580 gtk_widget_ensure_style(m_frameMenuBar
->m_widget
);
581 // have to call class method directly because
582 // "size_request" signal is overridden by wx
583 GTK_WIDGET_GET_CLASS(m_frameMenuBar
->m_widget
)->size_request(
584 m_frameMenuBar
->m_widget
, &req
);
586 m_menuBarHeight
= req
.height
;
589 // resize window in OnInternalIdle
593 bool wxFrame::HasVisibleMenubar() const
595 return m_frameMenuBar
&& m_frameMenuBar
->IsShown();
597 #endif // wxUSE_MENUS_NATIVE
601 wxToolBar
* wxFrame::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
603 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
605 InsertChildFunction save
= m_insertCallback
;
606 m_insertCallback
= wxInsertChildInFrame
;
607 m_frameToolBar
= wxFrameBase::CreateToolBar( style
, id
, name
);
608 m_insertCallback
= save
;
612 return m_frameToolBar
;
615 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
617 bool hadTbar
= m_frameToolBar
!= NULL
;
619 wxFrameBase::SetToolBar(toolbar
);
621 if ( m_frameToolBar
)
623 // insert into toolbar area if not already there
624 if ((m_frameToolBar
->m_widget
->parent
) &&
625 (m_frameToolBar
->m_widget
->parent
!= m_mainWidget
))
627 GetChildren().DeleteObject( m_frameToolBar
);
629 gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget
);
633 else // toolbar unset
635 // still need to update size if it had been there before
643 #endif // wxUSE_TOOLBAR
647 wxStatusBar
* wxFrame::CreateStatusBar(int number
,
650 const wxString
& name
)
652 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
654 // because it will change when toolbar is added
657 return wxFrameBase::CreateStatusBar( number
, style
, id
, name
);
660 void wxFrame::SetStatusBar(wxStatusBar
*statbar
)
662 bool hadStatBar
= m_frameStatusBar
!= NULL
;
664 wxFrameBase::SetStatusBar(statbar
);
666 if (hadStatBar
&& !m_frameStatusBar
)
670 void wxFrame::PositionStatusBar()
672 if ( !m_frameStatusBar
)
677 #endif // wxUSE_STATUSBAR