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"
25 #include "wx/gtk/win_gtk.h"
27 //-----------------------------------------------------------------------------
29 //-----------------------------------------------------------------------------
31 const int wxMENU_HEIGHT
= 27;
33 //-----------------------------------------------------------------------------
35 //-----------------------------------------------------------------------------
37 extern void wxapp_install_idle_handler();
40 //-----------------------------------------------------------------------------
42 //-----------------------------------------------------------------------------
44 extern wxList wxPendingDelete
;
46 //-----------------------------------------------------------------------------
48 //-----------------------------------------------------------------------------
51 gtk_mdi_page_change_callback( GtkNotebook
*WXUNUSED(widget
),
52 GtkNotebookPage
*page
,
53 gint
WXUNUSED(page_num
),
54 wxMDIParentFrame
*parent
)
57 wxapp_install_idle_handler();
59 // send deactivate event to old child
61 wxMDIChildFrame
*child
= parent
->GetActiveChild();
64 wxActivateEvent
event1( wxEVT_ACTIVATE
, FALSE
, child
->GetId() );
65 event1
.SetEventObject( child
);
66 child
->GetEventHandler()->ProcessEvent( event1
);
69 // send activate event to new child
71 wxMDIClientWindow
*client_window
= parent
->GetClientWindow();
75 child
= (wxMDIChildFrame
*) NULL
;
77 wxNode
*node
= client_window
->GetChildren().First();
80 wxMDIChildFrame
*child_frame
= (wxMDIChildFrame
*)node
->Data();
81 if (child_frame
->m_page
== page
)
92 wxActivateEvent
event2( wxEVT_ACTIVATE
, TRUE
, child
->GetId() );
93 event2
.SetEventObject( child
);
94 child
->GetEventHandler()->ProcessEvent( event2
);
97 //-----------------------------------------------------------------------------
99 //-----------------------------------------------------------------------------
101 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame
,wxFrame
)
103 void wxMDIParentFrame::Init()
105 m_justInserted
= FALSE
;
106 m_clientWindow
= (wxMDIClientWindow
*) NULL
;
109 wxMDIParentFrame::~wxMDIParentFrame()
113 bool wxMDIParentFrame::Create(wxWindow
*parent
,
115 const wxString
& title
,
119 const wxString
& name
)
121 wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name
);
128 void wxMDIParentFrame::GtkOnSize( int x
, int y
, int width
, int height
)
130 wxFrame::GtkOnSize( x
, y
, width
, height
);
132 wxMDIChildFrame
*child_frame
= GetActiveChild();
133 if (!child_frame
) return;
135 wxMenuBar
*menu_bar
= child_frame
->m_menuBar
;
136 if (!menu_bar
) return;
137 if (!menu_bar
->m_widget
) return;
141 menu_bar
->m_width
= m_width
;
142 menu_bar
->m_height
= wxMENU_HEIGHT
;
143 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
145 0, 0, m_width
, wxMENU_HEIGHT
);
148 void wxMDIParentFrame::OnInternalIdle()
150 /* if a an MDI child window has just been inserted
151 it has to be brought to the top in idle time. we
152 simply set the last notebook page active as new
153 pages can only be appended at the end */
157 GtkNotebook
*notebook
= GTK_NOTEBOOK(m_clientWindow
->m_widget
);
158 gtk_notebook_set_page( notebook
, g_list_length( notebook
->children
) - 1 );
160 m_justInserted
= FALSE
;
164 wxFrame::OnInternalIdle();
166 wxMDIChildFrame
*active_child_frame
= GetActiveChild();
167 bool visible_child_menu
= FALSE
;
169 wxNode
*node
= m_clientWindow
->GetChildren().First();
172 wxObject
*child
= node
->Data();
173 wxMDIChildFrame
*child_frame
= wxDynamicCast(child
, wxMDIChildFrame
);
176 wxMenuBar
*menu_bar
= child_frame
->m_menuBar
;
179 if (child_frame
== active_child_frame
)
181 if (menu_bar
->Show(TRUE
))
183 menu_bar
->m_width
= m_width
;
184 menu_bar
->m_height
= wxMENU_HEIGHT
;
185 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
187 0, 0, m_width
, wxMENU_HEIGHT
);
188 menu_bar
->SetInvokingWindow( child_frame
);
190 visible_child_menu
= TRUE
;
194 if (menu_bar
->Show(FALSE
))
196 menu_bar
->UnsetInvokingWindow( child_frame
);
205 /* show/hide parent menu bar as required */
206 if ((m_frameMenuBar
) &&
207 (m_frameMenuBar
->IsShown() == visible_child_menu
))
209 if (visible_child_menu
)
211 m_frameMenuBar
->Show( FALSE
);
212 m_frameMenuBar
->UnsetInvokingWindow( this );
216 m_frameMenuBar
->Show( TRUE
);
217 m_frameMenuBar
->SetInvokingWindow( this );
219 m_frameMenuBar
->m_width
= m_width
;
220 m_frameMenuBar
->m_height
= wxMENU_HEIGHT
;
221 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
222 m_frameMenuBar
->m_widget
,
223 0, 0, m_width
, wxMENU_HEIGHT
);
228 void wxMDIParentFrame::DoGetClientSize(int *width
, int *height
) const
230 wxFrame::DoGetClientSize( width
, height
);
233 wxMDIChildFrame
*wxMDIParentFrame::GetActiveChild() const
235 if (!m_clientWindow
) return (wxMDIChildFrame
*) NULL
;
237 GtkNotebook
*notebook
= GTK_NOTEBOOK(m_clientWindow
->m_widget
);
238 if (!notebook
) return (wxMDIChildFrame
*) NULL
;
240 gint i
= gtk_notebook_get_current_page( notebook
);
241 if (i
< 0) return (wxMDIChildFrame
*) NULL
;
243 GtkNotebookPage
* page
= (GtkNotebookPage
*) (g_list_nth(notebook
->children
,i
)->data
);
244 if (!page
) return (wxMDIChildFrame
*) NULL
;
246 wxNode
*node
= m_clientWindow
->GetChildren().First();
249 wxMDIChildFrame
*child_frame
= (wxMDIChildFrame
*)node
->Data();
250 if (child_frame
->m_page
== page
)
255 return (wxMDIChildFrame
*) NULL
;
258 wxMDIClientWindow
*wxMDIParentFrame::GetClientWindow() const
260 return m_clientWindow
;
263 wxMDIClientWindow
*wxMDIParentFrame::OnCreateClient()
265 m_clientWindow
= new wxMDIClientWindow( this );
266 return m_clientWindow
;
269 void wxMDIParentFrame::ActivateNext()
272 gtk_notebook_next_page( GTK_NOTEBOOK(m_clientWindow
->m_widget
) );
275 void wxMDIParentFrame::ActivatePrevious()
278 gtk_notebook_prev_page( GTK_NOTEBOOK(m_clientWindow
->m_widget
) );
281 //-----------------------------------------------------------------------------
283 //-----------------------------------------------------------------------------
285 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame
,wxFrame
)
287 BEGIN_EVENT_TABLE(wxMDIChildFrame
, wxFrame
)
288 EVT_ACTIVATE(wxMDIChildFrame::OnActivate
)
289 EVT_MENU_HIGHLIGHT_ALL(wxMDIChildFrame::OnMenuHighlight
)
292 wxMDIChildFrame::wxMDIChildFrame()
294 m_menuBar
= (wxMenuBar
*) NULL
;
295 m_page
= (GtkNotebookPage
*) NULL
;
298 wxMDIChildFrame::wxMDIChildFrame( wxMDIParentFrame
*parent
,
299 wxWindowID id
, const wxString
& title
,
300 const wxPoint
& WXUNUSED(pos
), const wxSize
& size
,
301 long style
, const wxString
& name
)
303 m_menuBar
= (wxMenuBar
*) NULL
;
304 m_page
= (GtkNotebookPage
*) NULL
;
305 Create( parent
, id
, title
, wxDefaultPosition
, size
, style
, name
);
308 wxMDIChildFrame::~wxMDIChildFrame()
314 bool wxMDIChildFrame::Create( wxMDIParentFrame
*parent
,
315 wxWindowID id
, const wxString
& title
,
316 const wxPoint
& WXUNUSED(pos
), const wxSize
& size
,
317 long style
, const wxString
& name
)
321 return wxWindow::Create( parent
->GetClientWindow(), id
, wxDefaultPosition
, size
, style
, name
);
324 void wxMDIChildFrame::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
326 wxWindow::DoSetSize( x
, y
, width
, height
, sizeFlags
);
329 void wxMDIChildFrame::DoSetClientSize(int width
, int height
)
331 wxWindow::DoSetClientSize( width
, height
);
334 void wxMDIChildFrame::DoGetClientSize( int *width
, int *height
) const
336 wxWindow::DoGetClientSize( width
, height
);
339 void wxMDIChildFrame::AddChild( wxWindowBase
*child
)
341 wxWindow::AddChild(child
);
344 void wxMDIChildFrame::SetMenuBar( wxMenuBar
*menu_bar
)
346 wxASSERT_MSG( m_menuBar
== NULL
, wxT("Only one menubar allowed") );
348 m_menuBar
= menu_bar
;
352 wxMDIParentFrame
*mdi_frame
= (wxMDIParentFrame
*)m_parent
->GetParent();
354 m_menuBar
->SetParent( mdi_frame
);
356 /* insert the invisible menu bar into the _parent_ mdi frame */
357 gtk_pizza_put( GTK_PIZZA(mdi_frame
->m_mainWidget
),
359 0, 0, mdi_frame
->m_width
, wxMENU_HEIGHT
);
363 wxMenuBar
*wxMDIChildFrame::GetMenuBar() const
368 void wxMDIChildFrame::Activate()
370 wxMDIParentFrame
* parent
= (wxMDIParentFrame
*) GetParent();
371 GtkNotebook
* notebook
= GTK_NOTEBOOK(parent
->m_widget
);
372 gint pageno
= gtk_notebook_page_num( notebook
, m_widget
);
373 gtk_notebook_set_page( notebook
, pageno
);
376 void wxMDIChildFrame::OnActivate( wxActivateEvent
& WXUNUSED(event
) )
380 void wxMDIChildFrame::OnMenuHighlight( wxMenuEvent
& event
)
383 wxMDIParentFrame
*mdi_frame
= (wxMDIParentFrame
*)m_parent
->GetParent();
384 if ( !ShowMenuHelp(mdi_frame
->GetStatusBar(), event
.GetMenuId()) )
386 // we don't have any help text for this item, but may be the MDI frame
388 mdi_frame
->OnMenuHighlight(event
);
390 #endif // wxUSE_STATUSBAR
393 void wxMDIChildFrame::SetTitle( const wxString
&title
)
395 if ( title
== m_title
)
400 wxMDIParentFrame
* parent
= (wxMDIParentFrame
*) GetParent();
401 GtkNotebook
* notebook
= GTK_NOTEBOOK(parent
->m_widget
);
402 gtk_notebook_set_tab_label_text(notebook
, m_widget
, title
.mbc_str());
405 //-----------------------------------------------------------------------------
407 //-----------------------------------------------------------------------------
409 static void gtk_page_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxWindow
*win
)
411 if (g_isIdle
) wxapp_install_idle_handler();
413 if ((win
->m_x
== alloc
->x
) &&
414 (win
->m_y
== alloc
->y
) &&
415 (win
->m_width
== alloc
->width
) &&
416 (win
->m_height
== alloc
->height
) &&
422 win
->SetSize( alloc
->x
, alloc
->y
, alloc
->width
, alloc
->height
);
425 //-----------------------------------------------------------------------------
426 // InsertChild callback for wxMDIClientWindow
427 //-----------------------------------------------------------------------------
429 static void wxInsertChildInMDI( wxMDIClientWindow
* parent
, wxMDIChildFrame
* child
)
431 wxString s
= child
->m_title
;
432 if (s
.IsNull()) s
= _("MDI child");
434 GtkWidget
*label_widget
= gtk_label_new( s
.mbc_str() );
435 gtk_misc_set_alignment( GTK_MISC(label_widget
), 0.0, 0.5 );
437 gtk_signal_connect( GTK_OBJECT(child
->m_widget
), "size_allocate",
438 GTK_SIGNAL_FUNC(gtk_page_size_callback
), (gpointer
)child
);
440 GtkNotebook
*notebook
= GTK_NOTEBOOK(parent
->m_widget
);
442 gtk_notebook_append_page( notebook
, child
->m_widget
, label_widget
);
444 child
->m_page
= (GtkNotebookPage
*) (g_list_last(notebook
->children
)->data
);
446 wxMDIParentFrame
*parent_frame
= (wxMDIParentFrame
*) parent
->GetParent();
447 parent_frame
->m_justInserted
= TRUE
;
450 //-----------------------------------------------------------------------------
452 //-----------------------------------------------------------------------------
454 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow
,wxWindow
)
456 wxMDIClientWindow::wxMDIClientWindow()
460 wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame
*parent
, long style
)
462 CreateClient( parent
, style
);
465 wxMDIClientWindow::~wxMDIClientWindow()
469 bool wxMDIClientWindow::CreateClient( wxMDIParentFrame
*parent
, long style
)
473 m_insertCallback
= (wxInsertChildFunction
)wxInsertChildInMDI
;
475 if (!PreCreation( parent
, wxDefaultPosition
, wxDefaultSize
) ||
476 !CreateBase( parent
, -1, wxDefaultPosition
, wxDefaultSize
, style
, wxDefaultValidator
, wxT("wxMDIClientWindow") ))
478 wxFAIL_MSG( wxT("wxMDIClientWindow creation failed") );
482 m_widget
= gtk_notebook_new();
484 gtk_signal_connect( GTK_OBJECT(m_widget
), "switch_page",
485 GTK_SIGNAL_FUNC(gtk_mdi_page_change_callback
), (gpointer
)parent
);
487 gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget
), 1 );
489 m_parent
->DoAddChild( this );