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 wxNode
*node
= client_window
->GetChildren().First();
81 wxMDIChildFrame
*child_frame
= (wxMDIChildFrame
*)node
->Data();
82 if (child_frame
->m_page
== page
)
93 wxActivateEvent
event2( wxEVT_ACTIVATE
, TRUE
, child
->GetId() );
94 event2
.SetEventObject( child
);
95 child
->GetEventHandler()->ProcessEvent( event2
);
98 //-----------------------------------------------------------------------------
100 //-----------------------------------------------------------------------------
102 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame
,wxFrame
)
104 void wxMDIParentFrame::Init()
106 m_justInserted
= FALSE
;
107 m_clientWindow
= (wxMDIClientWindow
*) NULL
;
110 wxMDIParentFrame::~wxMDIParentFrame()
114 bool wxMDIParentFrame::Create(wxWindow
*parent
,
116 const wxString
& title
,
120 const wxString
& name
)
122 wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name
);
129 void wxMDIParentFrame::GtkOnSize( int x
, int y
, int width
, int height
)
131 wxFrame::GtkOnSize( x
, y
, width
, height
);
133 wxMDIChildFrame
*child_frame
= GetActiveChild();
134 if (!child_frame
) return;
136 wxMenuBar
*menu_bar
= child_frame
->m_menuBar
;
137 if (!menu_bar
) return;
138 if (!menu_bar
->m_widget
) return;
142 menu_bar
->m_width
= m_width
;
143 menu_bar
->m_height
= wxMENU_HEIGHT
;
144 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
146 0, 0, m_width
, wxMENU_HEIGHT
);
149 void wxMDIParentFrame::OnInternalIdle()
151 /* if a an MDI child window has just been inserted
152 it has to be brought to the top in idle time. we
153 simply set the last notebook page active as new
154 pages can only be appended at the end */
158 GtkNotebook
*notebook
= GTK_NOTEBOOK(m_clientWindow
->m_widget
);
159 gtk_notebook_set_page( notebook
, g_list_length( notebook
->children
) - 1 );
161 m_justInserted
= FALSE
;
165 wxFrame::OnInternalIdle();
167 wxMDIChildFrame
*active_child_frame
= GetActiveChild();
168 bool visible_child_menu
= FALSE
;
170 wxNode
*node
= m_clientWindow
->GetChildren().First();
173 wxObject
*child
= node
->Data();
174 wxMDIChildFrame
*child_frame
= wxDynamicCast(child
, wxMDIChildFrame
);
177 wxMenuBar
*menu_bar
= child_frame
->m_menuBar
;
180 if (child_frame
== active_child_frame
)
182 if (menu_bar
->Show(TRUE
))
184 menu_bar
->m_width
= m_width
;
185 menu_bar
->m_height
= wxMENU_HEIGHT
;
186 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
188 0, 0, m_width
, wxMENU_HEIGHT
);
189 menu_bar
->SetInvokingWindow( child_frame
);
191 visible_child_menu
= TRUE
;
195 if (menu_bar
->Show(FALSE
))
197 menu_bar
->UnsetInvokingWindow( child_frame
);
206 /* show/hide parent menu bar as required */
207 if ((m_frameMenuBar
) &&
208 (m_frameMenuBar
->IsShown() == visible_child_menu
))
210 if (visible_child_menu
)
212 m_frameMenuBar
->Show( FALSE
);
213 m_frameMenuBar
->UnsetInvokingWindow( this );
217 m_frameMenuBar
->Show( TRUE
);
218 m_frameMenuBar
->SetInvokingWindow( this );
220 m_frameMenuBar
->m_width
= m_width
;
221 m_frameMenuBar
->m_height
= wxMENU_HEIGHT
;
222 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
223 m_frameMenuBar
->m_widget
,
224 0, 0, m_width
, wxMENU_HEIGHT
);
229 void wxMDIParentFrame::DoGetClientSize(int *width
, int *height
) const
231 wxFrame::DoGetClientSize( width
, height
);
234 wxMDIChildFrame
*wxMDIParentFrame::GetActiveChild() const
236 if (!m_clientWindow
) return (wxMDIChildFrame
*) NULL
;
238 GtkNotebook
*notebook
= GTK_NOTEBOOK(m_clientWindow
->m_widget
);
239 if (!notebook
) return (wxMDIChildFrame
*) NULL
;
241 gint i
= gtk_notebook_get_current_page( notebook
);
242 if (i
< 0) return (wxMDIChildFrame
*) NULL
;
244 GtkNotebookPage
* page
= (GtkNotebookPage
*) (g_list_nth(notebook
->children
,i
)->data
);
245 if (!page
) return (wxMDIChildFrame
*) NULL
;
247 wxNode
*node
= m_clientWindow
->GetChildren().First();
250 wxMDIChildFrame
*child_frame
= (wxMDIChildFrame
*)node
->Data();
251 if (child_frame
->m_page
== page
)
256 return (wxMDIChildFrame
*) NULL
;
259 wxMDIClientWindow
*wxMDIParentFrame::GetClientWindow() const
261 return m_clientWindow
;
264 wxMDIClientWindow
*wxMDIParentFrame::OnCreateClient()
266 m_clientWindow
= new wxMDIClientWindow( this );
267 return m_clientWindow
;
270 void wxMDIParentFrame::ActivateNext()
273 gtk_notebook_next_page( GTK_NOTEBOOK(m_clientWindow
->m_widget
) );
276 void wxMDIParentFrame::ActivatePrevious()
279 gtk_notebook_prev_page( GTK_NOTEBOOK(m_clientWindow
->m_widget
) );
282 //-----------------------------------------------------------------------------
284 //-----------------------------------------------------------------------------
286 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame
,wxFrame
)
288 BEGIN_EVENT_TABLE(wxMDIChildFrame
, wxFrame
)
289 EVT_ACTIVATE(wxMDIChildFrame::OnActivate
)
290 EVT_MENU_HIGHLIGHT_ALL(wxMDIChildFrame::OnMenuHighlight
)
293 wxMDIChildFrame::wxMDIChildFrame()
295 m_menuBar
= (wxMenuBar
*) NULL
;
296 m_page
= (GtkNotebookPage
*) NULL
;
299 wxMDIChildFrame::wxMDIChildFrame( wxMDIParentFrame
*parent
,
300 wxWindowID id
, const wxString
& title
,
301 const wxPoint
& WXUNUSED(pos
), const wxSize
& size
,
302 long style
, const wxString
& name
)
304 m_menuBar
= (wxMenuBar
*) NULL
;
305 m_page
= (GtkNotebookPage
*) NULL
;
306 Create( parent
, id
, title
, wxDefaultPosition
, size
, style
, name
);
309 wxMDIChildFrame::~wxMDIChildFrame()
315 bool wxMDIChildFrame::Create( wxMDIParentFrame
*parent
,
316 wxWindowID id
, const wxString
& title
,
317 const wxPoint
& WXUNUSED(pos
), const wxSize
& size
,
318 long style
, const wxString
& name
)
322 return wxWindow::Create( parent
->GetClientWindow(), id
, wxDefaultPosition
, size
, style
, name
);
325 void wxMDIChildFrame::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
327 wxWindow::DoSetSize( x
, y
, width
, height
, sizeFlags
);
330 void wxMDIChildFrame::DoSetClientSize(int width
, int height
)
332 wxWindow::DoSetClientSize( width
, height
);
335 void wxMDIChildFrame::DoGetClientSize( int *width
, int *height
) const
337 wxWindow::DoGetClientSize( width
, height
);
340 void wxMDIChildFrame::AddChild( wxWindowBase
*child
)
342 wxWindow::AddChild(child
);
345 void wxMDIChildFrame::SetMenuBar( wxMenuBar
*menu_bar
)
347 wxASSERT_MSG( m_menuBar
== NULL
, wxT("Only one menubar allowed") );
349 m_menuBar
= menu_bar
;
353 wxMDIParentFrame
*mdi_frame
= (wxMDIParentFrame
*)m_parent
->GetParent();
355 m_menuBar
->SetParent( mdi_frame
);
357 /* insert the invisible menu bar into the _parent_ mdi frame */
358 gtk_pizza_put( GTK_PIZZA(mdi_frame
->m_mainWidget
),
360 0, 0, mdi_frame
->m_width
, wxMENU_HEIGHT
);
364 wxMenuBar
*wxMDIChildFrame::GetMenuBar() const
369 void wxMDIChildFrame::Activate()
371 wxMDIParentFrame
* parent
= (wxMDIParentFrame
*) GetParent();
372 GtkNotebook
* notebook
= GTK_NOTEBOOK(parent
->m_widget
);
373 gint pageno
= gtk_notebook_page_num( notebook
, m_widget
);
374 gtk_notebook_set_page( notebook
, pageno
);
377 void wxMDIChildFrame::OnActivate( wxActivateEvent
& WXUNUSED(event
) )
381 void wxMDIChildFrame::OnMenuHighlight( wxMenuEvent
& event
)
384 wxMDIParentFrame
*mdi_frame
= (wxMDIParentFrame
*)m_parent
->GetParent();
385 if ( !ShowMenuHelp(mdi_frame
->GetStatusBar(), event
.GetMenuId()) )
387 // we don't have any help text for this item, but may be the MDI frame
389 mdi_frame
->OnMenuHighlight(event
);
391 #endif // wxUSE_STATUSBAR
394 void wxMDIChildFrame::SetTitle( const wxString
&title
)
396 if ( title
== m_title
)
401 wxMDIParentFrame
* parent
= (wxMDIParentFrame
*) GetParent();
402 GtkNotebook
* notebook
= GTK_NOTEBOOK(parent
->m_widget
);
403 gtk_notebook_set_tab_label_text(notebook
, m_widget
, wxGTK_CONV( title
) );
406 //-----------------------------------------------------------------------------
408 //-----------------------------------------------------------------------------
410 static void gtk_page_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxWindow
*win
)
412 if (g_isIdle
) wxapp_install_idle_handler();
414 if ((win
->m_x
== alloc
->x
) &&
415 (win
->m_y
== alloc
->y
) &&
416 (win
->m_width
== alloc
->width
) &&
417 (win
->m_height
== alloc
->height
) &&
423 win
->SetSize( alloc
->x
, alloc
->y
, alloc
->width
, alloc
->height
);
426 //-----------------------------------------------------------------------------
427 // InsertChild callback for wxMDIClientWindow
428 //-----------------------------------------------------------------------------
430 static void wxInsertChildInMDI( wxMDIClientWindow
* parent
, wxMDIChildFrame
* child
)
432 wxString s
= child
->m_title
;
433 if (s
.IsNull()) s
= _("MDI child");
435 GtkWidget
*label_widget
= gtk_label_new( s
.mbc_str() );
436 gtk_misc_set_alignment( GTK_MISC(label_widget
), 0.0, 0.5 );
438 gtk_signal_connect( GTK_OBJECT(child
->m_widget
), "size_allocate",
439 GTK_SIGNAL_FUNC(gtk_page_size_callback
), (gpointer
)child
);
441 GtkNotebook
*notebook
= GTK_NOTEBOOK(parent
->m_widget
);
443 gtk_notebook_append_page( notebook
, child
->m_widget
, label_widget
);
445 child
->m_page
= (GtkNotebookPage
*) (g_list_last(notebook
->children
)->data
);
447 wxMDIParentFrame
*parent_frame
= (wxMDIParentFrame
*) parent
->GetParent();
448 parent_frame
->m_justInserted
= TRUE
;
451 //-----------------------------------------------------------------------------
453 //-----------------------------------------------------------------------------
455 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow
,wxWindow
)
457 wxMDIClientWindow::wxMDIClientWindow()
461 wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame
*parent
, long style
)
463 CreateClient( parent
, style
);
466 wxMDIClientWindow::~wxMDIClientWindow()
470 bool wxMDIClientWindow::CreateClient( wxMDIParentFrame
*parent
, long style
)
474 m_insertCallback
= (wxInsertChildFunction
)wxInsertChildInMDI
;
476 if (!PreCreation( parent
, wxDefaultPosition
, wxDefaultSize
) ||
477 !CreateBase( parent
, -1, wxDefaultPosition
, wxDefaultSize
, style
, wxDefaultValidator
, wxT("wxMDIClientWindow") ))
479 wxFAIL_MSG( wxT("wxMDIClientWindow creation failed") );
483 m_widget
= gtk_notebook_new();
485 gtk_signal_connect( GTK_OBJECT(m_widget
), "switch_page",
486 GTK_SIGNAL_FUNC(gtk_mdi_page_change_callback
), (gpointer
)parent
);
488 gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget
), 1 );
490 m_parent
->DoAddChild( this );