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 (m_frameMenuBar 
&& 
 206             GTK_WIDGET_VISIBLE(m_frameMenuBar
->m_widget
) && !m_menuBarDetached
) 
 208             *height 
-= m_menuBarHeight
; 
 210 #endif // wxUSE_MENUS_NATIVE 
 214         if (m_frameStatusBar 
&& GTK_WIDGET_VISIBLE(m_frameStatusBar
->m_widget
)) 
 215             *height 
-= wxSTATUS_HEIGHT
; 
 216 #endif // wxUSE_STATUSBAR 
 221     if (m_frameToolBar 
&& 
 222         GTK_WIDGET_VISIBLE(m_frameToolBar
->m_widget
) && !m_toolBarDetached
) 
 224         if (m_frameToolBar
->IsVertical()) 
 227                 *width 
-= m_frameToolBar
->GetSize().x
; 
 232                 *height 
-= m_frameToolBar
->GetSize().y
; 
 235 #endif // wxUSE_TOOLBAR 
 237     if (width 
!= NULL 
&& *width 
< 0) 
 239     if (height 
!= NULL 
&& *height 
< 0) 
 243 bool wxFrame::ShowFullScreen(bool show
, long style
) 
 245     if (!wxFrameBase::ShowFullScreen(show
, style
)) 
 248     wxWindow
* const bar
[] = { 
 265     const long fsNoBar
[] = { 
 266         wxFULLSCREEN_NOMENUBAR
, wxFULLSCREEN_NOTOOLBAR
, wxFULLSCREEN_NOSTATUSBAR
 
 268     for (int i 
= 0; i 
< 3; i
++) 
 272             if (bar
[i
] && (style 
& fsNoBar
[i
])) 
 274                 if (bar
[i
]->IsShown()) 
 277                     style 
&= ~fsNoBar
[i
]; 
 282             if (bar
[i
] && (m_fsSaveFlag 
& fsNoBar
[i
])) 
 287         m_fsSaveFlag 
= style
; 
 292 void wxFrame::GtkOnSize() 
 295     if (m_resizing
) return; 
 298     // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow 
 299     wxASSERT_MSG( (m_wxwindow 
!= NULL
), wxT("invalid frame") ); 
 301     // space occupied by m_frameToolBar and m_frameMenuBar 
 302     int client_area_x_offset 
= 0, 
 303         client_area_y_offset 
= 0; 
 305     /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses 
 306        wxWindow::Create to create it's GTK equivalent. m_mainWidget is only 
 307        set in wxFrame::Create so it is used to check what kind of frame we 
 308        have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we 
 309        skip the part which handles m_frameMenuBar, m_frameToolBar and (most 
 310        importantly) m_mainWidget */ 
 317         // Rewrite this terrible code to using GtkVBox 
 319         // m_mainWidget holds the menubar, the toolbar and the client 
 320         // area, which is represented by m_wxwindow. 
 322 #if wxUSE_MENUS_NATIVE 
 323         if (m_frameMenuBar 
&& m_frameMenuBar
->IsShown()) 
 326             int yy 
= m_miniEdge 
+ m_miniTitle
; 
 327             int ww 
= m_width  
- 2*m_miniEdge
; 
 330             int hh 
= m_menuBarHeight
; 
 331             if (m_menuBarDetached
) hh 
= wxPLACE_HOLDER
; 
 332             m_frameMenuBar
->m_x 
= xx
; 
 333             m_frameMenuBar
->m_y 
= yy
; 
 334             m_frameMenuBar
->m_width 
= ww
; 
 335             m_frameMenuBar
->m_height 
= hh
; 
 336             gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
), 
 337                                   m_frameMenuBar
->m_widget
, 
 339             client_area_y_offset 
+= hh
; 
 341 #endif // wxUSE_MENUS_NATIVE 
 344         if ((m_frameToolBar
) && m_frameToolBar
->IsShown() && 
 345             (m_frameToolBar
->m_widget
->parent 
== m_mainWidget
)) 
 348             int yy 
= m_miniEdge 
+ m_miniTitle
; 
 349 #if wxUSE_MENUS_NATIVE 
 352                 if (!m_menuBarDetached
) 
 353                     yy 
+= m_menuBarHeight
; 
 355                     yy 
+= wxPLACE_HOLDER
; 
 357 #endif // wxUSE_MENUS_NATIVE 
 359             m_frameToolBar
->m_x 
= xx
; 
 360             m_frameToolBar
->m_y 
= yy
; 
 362             // don't change the toolbar's reported height/width 
 364             if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL 
) 
 366                 ww 
= m_toolBarDetached 
? wxPLACE_HOLDER
 
 367                                        : m_frameToolBar
->m_width
; 
 368                 hh 
= m_height 
- 2*m_miniEdge
; 
 370                 client_area_x_offset 
+= ww
; 
 372             else if( m_frameToolBar
->HasFlag(wxTB_RIGHT
) ) 
 375                ww 
= m_toolBarDetached 
? wxPLACE_HOLDER
 
 376                                       : m_frameToolBar
->m_width
; 
 377                xx 
= GetClientSize().x 
- 1; 
 378                hh 
= m_height 
- 2*m_miniEdge
; 
 383             else if( m_frameToolBar
->GetWindowStyle() & wxTB_BOTTOM 
) 
 386                 yy 
= GetClientSize().y
; 
 387 #if wxUSE_MENUS_NATIVE 
 388                 yy 
+= m_menuBarHeight
; 
 389 #endif // wxUSE_MENU_NATIVE 
 390                 m_frameToolBar
->m_x 
= xx
; 
 391                 m_frameToolBar
->m_y 
= yy
; 
 392                 ww 
= m_width 
- 2*m_miniEdge
; 
 393                 hh 
= m_toolBarDetached 
? wxPLACE_HOLDER
 
 394                                        : m_frameToolBar
->m_height
; 
 398                 ww 
= m_width 
- 2*m_miniEdge
; 
 399                 hh 
= m_toolBarDetached 
? wxPLACE_HOLDER
 
 400                                        : m_frameToolBar
->m_height
; 
 402                 client_area_y_offset 
+= hh
; 
 409             gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
), 
 410                                   m_frameToolBar
->m_widget
, 
 413 #endif // wxUSE_TOOLBAR 
 415         int client_x 
= client_area_x_offset 
+ m_miniEdge
; 
 416         int client_y 
= client_area_y_offset 
+ m_miniEdge 
+ m_miniTitle
; 
 417         int client_w 
= m_width 
- client_area_x_offset 
- 2*m_miniEdge
; 
 418         int client_h 
= m_height 
- client_area_y_offset
- 2*m_miniEdge 
- m_miniTitle
; 
 423         gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
), 
 425                               client_x
, client_y
, client_w
, client_h 
); 
 429         // If there is no m_mainWidget between m_widget and m_wxwindow there 
 430         // is no need to set the size or position of m_wxwindow. 
 434     if (m_frameStatusBar 
&& m_frameStatusBar
->IsShown()) 
 436         int xx 
= 0 + m_miniEdge
; 
 437         int yy 
= m_height 
- wxSTATUS_HEIGHT 
- m_miniEdge 
- client_area_y_offset
; 
 438         int ww 
= m_width 
- 2*m_miniEdge
; 
 441         int hh 
= wxSTATUS_HEIGHT
; 
 442         m_frameStatusBar
->m_x 
= xx
; 
 443         m_frameStatusBar
->m_y 
= yy
; 
 444         m_frameStatusBar
->m_width 
= ww
; 
 445         m_frameStatusBar
->m_height 
= hh
; 
 446         gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
), 
 447                             m_frameStatusBar
->m_widget
, 
 450 #endif // wxUSE_STATUSBAR 
 454     // send size event to frame 
 455     wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
 456     event
.SetEventObject( this ); 
 457     GetEventHandler()->ProcessEvent( event 
); 
 460     // send size event to status bar 
 461     if (m_frameStatusBar
) 
 463         wxSizeEvent 
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() ); 
 464         event2
.SetEventObject( m_frameStatusBar 
); 
 465         m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2 
); 
 467 #endif // wxUSE_STATUSBAR 
 472 void wxFrame::OnInternalIdle() 
 474     wxFrameBase::OnInternalIdle(); 
 476 #if wxUSE_MENUS_NATIVE 
 477     if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle(); 
 478 #endif // wxUSE_MENUS_NATIVE 
 480     if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle(); 
 483     if (m_frameStatusBar
) 
 485         m_frameStatusBar
->OnInternalIdle(); 
 487         // There may be controls in the status bar that 
 488         // need to be updated 
 489         for ( wxWindowList::compatibility_iterator node 
= m_frameStatusBar
->GetChildren().GetFirst(); 
 491           node 
= node
->GetNext() ) 
 493             wxWindow 
*child 
= node
->GetData(); 
 494             child
->OnInternalIdle(); 
 500 // ---------------------------------------------------------------------------- 
 501 // menu/tool/status bar stuff 
 502 // ---------------------------------------------------------------------------- 
 504 #if wxUSE_MENUS_NATIVE 
 506 void wxFrame::DetachMenuBar() 
 508     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 509     wxASSERT_MSG( (m_wxwindow 
!= NULL
), wxT("invalid frame") ); 
 511     if ( m_frameMenuBar 
) 
 513         m_frameMenuBar
->UnsetInvokingWindow( this ); 
 515         if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
) 
 517             g_signal_handlers_disconnect_by_func (m_frameMenuBar
->m_widget
, 
 518                     (gpointer
) gtk_menu_attached_callback
, 
 521             g_signal_handlers_disconnect_by_func (m_frameMenuBar
->m_widget
, 
 522                     (gpointer
) gtk_menu_detached_callback
, 
 526         gtk_widget_ref( m_frameMenuBar
->m_widget 
); 
 528         gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget 
); 
 531     wxFrameBase::DetachMenuBar(); 
 534 void wxFrame::AttachMenuBar( wxMenuBar 
*menuBar 
) 
 536     wxFrameBase::AttachMenuBar(menuBar
); 
 540         m_frameMenuBar
->SetInvokingWindow( this ); 
 542         m_frameMenuBar
->SetParent(this); 
 543         gtk_pizza_put( GTK_PIZZA(m_mainWidget
), 
 544                 m_frameMenuBar
->m_widget
, 
 547                 m_frameMenuBar
->m_width
, 
 548                 m_frameMenuBar
->m_height 
); 
 550         if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
) 
 552             g_signal_connect (menuBar
->m_widget
, "child_attached", 
 553                               G_CALLBACK (gtk_menu_attached_callback
), 
 555             g_signal_connect (menuBar
->m_widget
, "child_detached", 
 556                               G_CALLBACK (gtk_menu_detached_callback
), 
 560         gtk_widget_show( m_frameMenuBar
->m_widget 
); 
 567         GtkUpdateSize();        // resize window in OnInternalIdle 
 571 void wxFrame::UpdateMenuBarSize() 
 575     // this is called after Remove with a NULL m_frameMenuBar 
 576     if ( m_frameMenuBar 
) 
 579         gtk_widget_ensure_style(m_frameMenuBar
->m_widget
); 
 580         // have to call class method directly because 
 581         // "size_request" signal is overridden by wx 
 582         GTK_WIDGET_GET_CLASS(m_frameMenuBar
->m_widget
)->size_request( 
 583             m_frameMenuBar
->m_widget
, &req
); 
 585         m_menuBarHeight 
= req
.height
; 
 588     // resize window in OnInternalIdle 
 592 #endif // wxUSE_MENUS_NATIVE 
 596 wxToolBar
* wxFrame::CreateToolBar( long style
, wxWindowID id
, const wxString
& name 
) 
 598     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 600     InsertChildFunction save 
= m_insertCallback
; 
 601     m_insertCallback 
= wxInsertChildInFrame
; 
 602     m_frameToolBar 
= wxFrameBase::CreateToolBar( style
, id
, name 
); 
 603     m_insertCallback 
= save
; 
 607     return m_frameToolBar
; 
 610 void wxFrame::SetToolBar(wxToolBar 
*toolbar
) 
 612     bool hadTbar 
= m_frameToolBar 
!= NULL
; 
 614     wxFrameBase::SetToolBar(toolbar
); 
 616     if ( m_frameToolBar 
) 
 618         // insert into toolbar area if not already there 
 619         if ((m_frameToolBar
->m_widget
->parent
) && 
 620             (m_frameToolBar
->m_widget
->parent 
!= m_mainWidget
)) 
 622             GetChildren().DeleteObject( m_frameToolBar 
); 
 624             gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget 
); 
 628     else // toolbar unset 
 630         // still need to update size if it had been there before 
 638 #endif // wxUSE_TOOLBAR 
 642 wxStatusBar
* wxFrame::CreateStatusBar(int number
, 
 645                                       const wxString
& name
) 
 647     wxASSERT_MSG( (m_widget 
!= NULL
), wxT("invalid frame") ); 
 649     // because it will change when toolbar is added 
 652     return wxFrameBase::CreateStatusBar( number
, style
, id
, name 
); 
 655 void wxFrame::SetStatusBar(wxStatusBar 
*statbar
) 
 657     bool hadStatBar 
= m_frameStatusBar 
!= NULL
; 
 659     wxFrameBase::SetStatusBar(statbar
); 
 661     if (hadStatBar 
&& !m_frameStatusBar
) 
 665 void wxFrame::PositionStatusBar() 
 667     if ( !m_frameStatusBar 
) 
 672 #endif // wxUSE_STATUSBAR