1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  11 #pragma implementation "mdi.h" 
  16 #if wxUSE_MDI_ARCHITECTURE 
  18 #include "wx/dialog.h" 
  21 #include "wx/gtk/private.h" 
  26 #include "wx/gtk/win_gtk.h" 
  28 //----------------------------------------------------------------------------- 
  30 //----------------------------------------------------------------------------- 
  32 const int wxMENU_HEIGHT 
= 27; 
  34 //----------------------------------------------------------------------------- 
  36 //----------------------------------------------------------------------------- 
  38 extern void wxapp_install_idle_handler(); 
  41 //----------------------------------------------------------------------------- 
  43 //----------------------------------------------------------------------------- 
  45 extern wxList wxPendingDelete
; 
  47 //----------------------------------------------------------------------------- 
  49 //----------------------------------------------------------------------------- 
  52 gtk_mdi_page_change_callback( GtkNotebook 
*WXUNUSED(widget
), 
  53                               GtkNotebookPage 
*page
, 
  54                               gint 
WXUNUSED(page_num
), 
  55                               wxMDIParentFrame 
*parent 
) 
  58         wxapp_install_idle_handler(); 
  60     // send deactivate event to old child 
  62     wxMDIChildFrame 
*child 
= parent
->GetActiveChild(); 
  65         wxActivateEvent 
event1( wxEVT_ACTIVATE
, false, child
->GetId() ); 
  66         event1
.SetEventObject( child
); 
  67         child
->GetEventHandler()->ProcessEvent( event1 
); 
  70     // send activate event to new child 
  72     wxMDIClientWindow 
*client_window 
= parent
->GetClientWindow(); 
  76     child 
= (wxMDIChildFrame
*) NULL
; 
  78     wxWindowList::Node  
*node 
= client_window
->GetChildren().GetFirst(); 
  81         wxMDIChildFrame 
*child_frame 
= wxDynamicCast( node
->GetData(), wxMDIChildFrame 
); 
  83         wxASSERT_MSG( child_frame
, _T("child is not a wxMDIChildFrame") ); 
  85         if (child_frame
->m_page 
== page
) 
  90         node 
= node
->GetNext(); 
  96     wxActivateEvent 
event2( wxEVT_ACTIVATE
, true, child
->GetId() ); 
  97     event2
.SetEventObject( child
); 
  98     child
->GetEventHandler()->ProcessEvent( event2 
); 
 101 //----------------------------------------------------------------------------- 
 103 //----------------------------------------------------------------------------- 
 105 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame
,wxFrame
) 
 107 void wxMDIParentFrame::Init() 
 109     m_justInserted 
= false; 
 110     m_clientWindow 
= (wxMDIClientWindow 
*) NULL
; 
 113 wxMDIParentFrame::~wxMDIParentFrame() 
 117 bool wxMDIParentFrame::Create(wxWindow 
*parent
, 
 119                               const wxString
& title
, 
 123                               const wxString
& name 
) 
 125     wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name 
); 
 132 void wxMDIParentFrame::GtkOnSize( int x
, int y
, int width
, int height 
) 
 134     wxFrame::GtkOnSize( x
, y
, width
, height 
); 
 136     wxMDIChildFrame 
*child_frame 
= GetActiveChild(); 
 137     if (!child_frame
) return; 
 139     wxMenuBar 
*menu_bar 
= child_frame
->m_menuBar
; 
 140     if (!menu_bar
) return; 
 141     if (!menu_bar
->m_widget
) return; 
 145     menu_bar
->m_width 
= m_width
; 
 146     menu_bar
->m_height 
= wxMENU_HEIGHT
; 
 147     gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
), 
 149                           0, 0, m_width
, wxMENU_HEIGHT 
); 
 152 void wxMDIParentFrame::OnInternalIdle() 
 154     /* if a an MDI child window has just been inserted 
 155        it has to be brought to the top in idle time. we 
 156        simply set the last notebook page active as new 
 157        pages can only be appended at the end */ 
 161         GtkNotebook 
*notebook 
= GTK_NOTEBOOK(m_clientWindow
->m_widget
); 
 162         gtk_notebook_set_page( notebook
, g_list_length( notebook
->children 
) - 1 ); 
 164         m_justInserted 
= false; 
 168     wxFrame::OnInternalIdle(); 
 170     wxMDIChildFrame 
*active_child_frame 
= GetActiveChild(); 
 171     bool visible_child_menu 
= false; 
 173     wxWindowList::Node     
*node 
= m_clientWindow
->GetChildren().GetFirst(); 
 176         wxMDIChildFrame 
*child_frame 
= wxDynamicCast( node
->GetData(), wxMDIChildFrame 
); 
 180             wxMenuBar 
*menu_bar 
= child_frame
->m_menuBar
; 
 183                 if (child_frame 
== active_child_frame
) 
 185                     if (menu_bar
->Show(true)) 
 187                         menu_bar
->m_width 
= m_width
; 
 188                         menu_bar
->m_height 
= wxMENU_HEIGHT
; 
 189                         gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
), 
 191                                             0, 0, m_width
, wxMENU_HEIGHT 
); 
 192                         menu_bar
->SetInvokingWindow( child_frame 
); 
 194                     visible_child_menu 
= true; 
 198                     if (menu_bar
->Show(false)) 
 200                         menu_bar
->UnsetInvokingWindow( child_frame 
); 
 206         node 
= node
->GetNext(); 
 209     /* show/hide parent menu bar as required */ 
 210     if ((m_frameMenuBar
) && 
 211         (m_frameMenuBar
->IsShown() == visible_child_menu
)) 
 213         if (visible_child_menu
) 
 215             m_frameMenuBar
->Show( false ); 
 216             m_frameMenuBar
->UnsetInvokingWindow( this ); 
 220             m_frameMenuBar
->Show( true ); 
 221             m_frameMenuBar
->SetInvokingWindow( this ); 
 223             m_frameMenuBar
->m_width 
= m_width
; 
 224             m_frameMenuBar
->m_height 
= wxMENU_HEIGHT
; 
 225             gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
), 
 226                                 m_frameMenuBar
->m_widget
, 
 227                                 0, 0, m_width
, wxMENU_HEIGHT 
); 
 232 void wxMDIParentFrame::DoGetClientSize(int *width
, int *height 
) const 
 234     wxFrame::DoGetClientSize( width
, height 
); 
 237 wxMDIChildFrame 
*wxMDIParentFrame::GetActiveChild() const 
 239     if (!m_clientWindow
) return (wxMDIChildFrame
*) NULL
; 
 241     GtkNotebook 
*notebook 
= GTK_NOTEBOOK(m_clientWindow
->m_widget
); 
 242     if (!notebook
) return (wxMDIChildFrame
*) NULL
; 
 244     gint i 
= gtk_notebook_get_current_page( notebook 
); 
 245     if (i 
< 0) return (wxMDIChildFrame
*) NULL
; 
 247     GtkNotebookPage
* page 
= (GtkNotebookPage
*) (g_list_nth(notebook
->children
,i
)->data
); 
 248     if (!page
) return (wxMDIChildFrame
*) NULL
; 
 250     wxWindowList::Node  
*node 
= m_clientWindow
->GetChildren().GetFirst(); 
 253         wxMDIChildFrame 
*child_frame 
= wxDynamicCast( node
->GetData(), wxMDIChildFrame 
); 
 255         wxASSERT_MSG( child_frame
, _T("child is not a wxMDIChildFrame") ); 
 257         if (child_frame
->m_page 
== page
) 
 259         node 
= node
->GetNext(); 
 262     return (wxMDIChildFrame
*) NULL
; 
 265 wxMDIClientWindow 
*wxMDIParentFrame::GetClientWindow() const 
 267     return m_clientWindow
; 
 270 wxMDIClientWindow 
*wxMDIParentFrame::OnCreateClient() 
 272     m_clientWindow 
= new wxMDIClientWindow( this ); 
 273     return m_clientWindow
; 
 276 void wxMDIParentFrame::ActivateNext() 
 279       gtk_notebook_next_page( GTK_NOTEBOOK(m_clientWindow
->m_widget
) ); 
 282 void wxMDIParentFrame::ActivatePrevious() 
 285       gtk_notebook_prev_page( GTK_NOTEBOOK(m_clientWindow
->m_widget
) ); 
 288 //----------------------------------------------------------------------------- 
 290 //----------------------------------------------------------------------------- 
 292 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame
,wxFrame
) 
 294 BEGIN_EVENT_TABLE(wxMDIChildFrame
, wxFrame
) 
 295     EVT_ACTIVATE(wxMDIChildFrame::OnActivate
) 
 296     EVT_MENU_HIGHLIGHT_ALL(wxMDIChildFrame::OnMenuHighlight
) 
 299 wxMDIChildFrame::wxMDIChildFrame() 
 301     m_menuBar 
= (wxMenuBar 
*) NULL
; 
 302     m_page 
= (GtkNotebookPage 
*) NULL
; 
 305 wxMDIChildFrame::wxMDIChildFrame( wxMDIParentFrame 
*parent
, 
 306       wxWindowID id
, const wxString
& title
, 
 307       const wxPoint
& WXUNUSED(pos
), const wxSize
& size
, 
 308       long style
, const wxString
& name 
) 
 310     m_menuBar 
= (wxMenuBar 
*) NULL
; 
 311     m_page 
= (GtkNotebookPage 
*) NULL
; 
 312     Create( parent
, id
, title
, wxDefaultPosition
, size
, style
, name 
); 
 315 wxMDIChildFrame::~wxMDIChildFrame() 
 321 bool wxMDIChildFrame::Create( wxMDIParentFrame 
*parent
, 
 322       wxWindowID id
, const wxString
& title
, 
 323       const wxPoint
& WXUNUSED(pos
), const wxSize
& size
, 
 324       long style
, const wxString
& name 
) 
 328     return wxWindow::Create( parent
->GetClientWindow(), id
, wxDefaultPosition
, size
, style
, name 
); 
 331 void wxMDIChildFrame::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
 333     wxWindow::DoSetSize( x
, y
, width
, height
, sizeFlags 
); 
 336 void wxMDIChildFrame::DoSetClientSize(int width
, int height
) 
 338     wxWindow::DoSetClientSize( width
, height 
); 
 341 void wxMDIChildFrame::DoGetClientSize( int *width
, int *height 
) const 
 343     wxWindow::DoGetClientSize( width
, height 
); 
 346 void wxMDIChildFrame::AddChild( wxWindowBase 
*child 
) 
 348     wxWindow::AddChild(child
); 
 351 void wxMDIChildFrame::SetMenuBar( wxMenuBar 
*menu_bar 
) 
 353     wxASSERT_MSG( m_menuBar 
== NULL
, wxT("Only one menubar allowed") ); 
 355     m_menuBar 
= menu_bar
; 
 359         wxMDIParentFrame 
*mdi_frame 
= (wxMDIParentFrame
*)m_parent
->GetParent(); 
 361         m_menuBar
->SetParent( mdi_frame 
); 
 363         /* insert the invisible menu bar into the _parent_ mdi frame */ 
 364         gtk_pizza_put( GTK_PIZZA(mdi_frame
->m_mainWidget
), 
 366                          0, 0,  mdi_frame
->m_width
, wxMENU_HEIGHT 
); 
 370 wxMenuBar 
*wxMDIChildFrame::GetMenuBar() const 
 375 void wxMDIChildFrame::Activate() 
 377     wxMDIParentFrame
* parent 
= (wxMDIParentFrame
*) GetParent(); 
 378     GtkNotebook
* notebook 
= GTK_NOTEBOOK(parent
->m_widget
); 
 379     gint pageno 
= gtk_notebook_page_num( notebook
, m_widget 
); 
 380     gtk_notebook_set_page( notebook
, pageno 
); 
 383 void wxMDIChildFrame::OnActivate( wxActivateEvent
& WXUNUSED(event
) ) 
 387 void wxMDIChildFrame::OnMenuHighlight( wxMenuEvent
& event 
) 
 390     wxMDIParentFrame 
*mdi_frame 
= (wxMDIParentFrame
*)m_parent
->GetParent(); 
 391     if ( !ShowMenuHelp(mdi_frame
->GetStatusBar(), event
.GetMenuId()) ) 
 393         // we don't have any help text for this item, but may be the MDI frame 
 395         mdi_frame
->OnMenuHighlight(event
); 
 397 #endif // wxUSE_STATUSBAR 
 400 void wxMDIChildFrame::SetTitle( const wxString 
&title 
) 
 402     if ( title 
== m_title 
) 
 407     wxMDIParentFrame
* parent 
= (wxMDIParentFrame
*) GetParent(); 
 408     GtkNotebook
* notebook 
= GTK_NOTEBOOK(parent
->m_widget
); 
 409     gtk_notebook_set_tab_label_text(notebook
, m_widget
, wxGTK_CONV( title 
) ); 
 412 //----------------------------------------------------------------------------- 
 414 //----------------------------------------------------------------------------- 
 416 static void gtk_page_size_callback( GtkWidget 
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxWindow 
*win 
) 
 418     if (g_isIdle
) wxapp_install_idle_handler(); 
 420     if ((win
->m_x 
== alloc
->x
) && 
 421         (win
->m_y 
== alloc
->y
) && 
 422         (win
->m_width 
== alloc
->width
) && 
 423         (win
->m_height 
== alloc
->height
) && 
 429     win
->SetSize( alloc
->x
, alloc
->y
, alloc
->width
, alloc
->height 
); 
 432 //----------------------------------------------------------------------------- 
 433 // InsertChild callback for wxMDIClientWindow 
 434 //----------------------------------------------------------------------------- 
 436 static void wxInsertChildInMDI( wxMDIClientWindow
* parent
, wxMDIChildFrame
* child 
) 
 438     wxString s 
= child
->m_title
; 
 439     if (s
.IsNull()) s 
= _("MDI child"); 
 441     GtkWidget 
*label_widget 
= gtk_label_new( s
.mbc_str() ); 
 442     gtk_misc_set_alignment( GTK_MISC(label_widget
), 0.0, 0.5 ); 
 444     gtk_signal_connect( GTK_OBJECT(child
->m_widget
), "size_allocate", 
 445       GTK_SIGNAL_FUNC(gtk_page_size_callback
), (gpointer
)child 
); 
 447     GtkNotebook 
*notebook 
= GTK_NOTEBOOK(parent
->m_widget
); 
 449     gtk_notebook_append_page( notebook
, child
->m_widget
, label_widget 
); 
 451     child
->m_page 
= (GtkNotebookPage
*) (g_list_last(notebook
->children
)->data
); 
 453     wxMDIParentFrame 
*parent_frame 
= (wxMDIParentFrame
*) parent
->GetParent(); 
 454     parent_frame
->m_justInserted 
= true; 
 457 //----------------------------------------------------------------------------- 
 459 //----------------------------------------------------------------------------- 
 461 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow
,wxWindow
) 
 463 wxMDIClientWindow::wxMDIClientWindow() 
 467 wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame 
*parent
, long style 
) 
 469     CreateClient( parent
, style 
); 
 472 wxMDIClientWindow::~wxMDIClientWindow() 
 476 bool wxMDIClientWindow::CreateClient( wxMDIParentFrame 
*parent
, long style 
) 
 480     m_insertCallback 
= (wxInsertChildFunction
)wxInsertChildInMDI
; 
 482     if (!PreCreation( parent
, wxDefaultPosition
, wxDefaultSize 
) || 
 483         !CreateBase( parent
, -1, wxDefaultPosition
, wxDefaultSize
, style
, wxDefaultValidator
, wxT("wxMDIClientWindow") )) 
 485         wxFAIL_MSG( wxT("wxMDIClientWindow creation failed") ); 
 489     m_widget 
= gtk_notebook_new(); 
 491     gtk_signal_connect( GTK_OBJECT(m_widget
), "switch_page", 
 492       GTK_SIGNAL_FUNC(gtk_mdi_page_change_callback
), (gpointer
)parent 
); 
 494     gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget
), 1 ); 
 496     m_parent
->DoAddChild( this );