1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
11 #pragma implementation "mdi.h"
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
21 #include "wx/dialog.h"
24 #include "wx/gtk/private.h"
29 #include "wx/gtk/win_gtk.h"
31 //-----------------------------------------------------------------------------
33 //-----------------------------------------------------------------------------
35 const int wxMENU_HEIGHT
= 27;
37 //-----------------------------------------------------------------------------
39 //-----------------------------------------------------------------------------
41 extern void wxapp_install_idle_handler();
44 //-----------------------------------------------------------------------------
46 //-----------------------------------------------------------------------------
48 extern wxList wxPendingDelete
;
50 //-----------------------------------------------------------------------------
52 //-----------------------------------------------------------------------------
55 gtk_mdi_page_change_callback( GtkNotebook
*WXUNUSED(widget
),
56 GtkNotebookPage
*page
,
57 gint
WXUNUSED(page_num
),
58 wxMDIParentFrame
*parent
)
61 wxapp_install_idle_handler();
63 // send deactivate event to old child
65 wxMDIChildFrame
*child
= parent
->GetActiveChild();
68 wxActivateEvent
event1( wxEVT_ACTIVATE
, false, child
->GetId() );
69 event1
.SetEventObject( child
);
70 child
->GetEventHandler()->ProcessEvent( event1
);
73 // send activate event to new child
75 wxMDIClientWindow
*client_window
= parent
->GetClientWindow();
79 child
= (wxMDIChildFrame
*) NULL
;
81 wxWindowList::compatibility_iterator node
= client_window
->GetChildren().GetFirst();
84 wxMDIChildFrame
*child_frame
= wxDynamicCast( node
->GetData(), wxMDIChildFrame
);
86 wxASSERT_MSG( child_frame
, _T("child is not a wxMDIChildFrame") );
88 if (child_frame
->m_page
== page
)
93 node
= node
->GetNext();
99 wxActivateEvent
event2( wxEVT_ACTIVATE
, true, child
->GetId() );
100 event2
.SetEventObject( child
);
101 child
->GetEventHandler()->ProcessEvent( event2
);
104 //-----------------------------------------------------------------------------
106 //-----------------------------------------------------------------------------
108 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame
,wxFrame
)
110 void wxMDIParentFrame::Init()
112 m_justInserted
= false;
113 m_clientWindow
= (wxMDIClientWindow
*) NULL
;
116 wxMDIParentFrame::~wxMDIParentFrame()
120 bool wxMDIParentFrame::Create(wxWindow
*parent
,
122 const wxString
& title
,
126 const wxString
& name
)
128 wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name
);
135 void wxMDIParentFrame::GtkOnSize( int x
, int y
, int width
, int height
)
137 wxFrame::GtkOnSize( x
, y
, width
, height
);
139 wxMDIChildFrame
*child_frame
= GetActiveChild();
140 if (!child_frame
) return;
142 wxMenuBar
*menu_bar
= child_frame
->m_menuBar
;
143 if (!menu_bar
) return;
144 if (!menu_bar
->m_widget
) return;
148 menu_bar
->m_width
= m_width
;
149 menu_bar
->m_height
= wxMENU_HEIGHT
;
150 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
152 0, 0, m_width
, wxMENU_HEIGHT
);
155 void wxMDIParentFrame::OnInternalIdle()
157 /* if a an MDI child window has just been inserted
158 it has to be brought to the top in idle time. we
159 simply set the last notebook page active as new
160 pages can only be appended at the end */
164 GtkNotebook
*notebook
= GTK_NOTEBOOK(m_clientWindow
->m_widget
);
165 gtk_notebook_set_page( notebook
, g_list_length( notebook
->children
) - 1 );
167 /* need to set the menubar of the child */
168 wxMDIChildFrame
*active_child_frame
= GetActiveChild();
169 wxMenuBar
*menu_bar
= active_child_frame
->m_menuBar
;
170 menu_bar
->m_width
= m_width
;
171 menu_bar
->m_height
= wxMENU_HEIGHT
;
172 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
174 0, 0, m_width
, wxMENU_HEIGHT
);
175 menu_bar
->SetInvokingWindow(active_child_frame
);
177 m_justInserted
= false;
181 wxFrame::OnInternalIdle();
183 wxMDIChildFrame
*active_child_frame
= GetActiveChild();
184 bool visible_child_menu
= false;
186 wxWindowList::compatibility_iterator node
= m_clientWindow
->GetChildren().GetFirst();
189 wxMDIChildFrame
*child_frame
= wxDynamicCast( node
->GetData(), wxMDIChildFrame
);
193 wxMenuBar
*menu_bar
= child_frame
->m_menuBar
;
196 if (child_frame
== active_child_frame
)
198 if (menu_bar
->Show(true))
200 menu_bar
->m_width
= m_width
;
201 menu_bar
->m_height
= wxMENU_HEIGHT
;
202 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
204 0, 0, m_width
, wxMENU_HEIGHT
);
205 menu_bar
->SetInvokingWindow( child_frame
);
207 visible_child_menu
= true;
211 if (menu_bar
->Show(false))
213 menu_bar
->UnsetInvokingWindow( child_frame
);
219 node
= node
->GetNext();
222 /* show/hide parent menu bar as required */
223 if ((m_frameMenuBar
) &&
224 (m_frameMenuBar
->IsShown() == visible_child_menu
))
226 if (visible_child_menu
)
228 m_frameMenuBar
->Show( false );
229 m_frameMenuBar
->UnsetInvokingWindow( this );
233 m_frameMenuBar
->Show( true );
234 m_frameMenuBar
->SetInvokingWindow( this );
236 m_frameMenuBar
->m_width
= m_width
;
237 m_frameMenuBar
->m_height
= wxMENU_HEIGHT
;
238 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
239 m_frameMenuBar
->m_widget
,
240 0, 0, m_width
, wxMENU_HEIGHT
);
245 void wxMDIParentFrame::DoGetClientSize(int *width
, int *height
) const
247 wxFrame::DoGetClientSize( width
, height
);
250 wxMDIChildFrame
*wxMDIParentFrame::GetActiveChild() const
252 if (!m_clientWindow
) return (wxMDIChildFrame
*) NULL
;
254 GtkNotebook
*notebook
= GTK_NOTEBOOK(m_clientWindow
->m_widget
);
255 if (!notebook
) return (wxMDIChildFrame
*) NULL
;
257 gint i
= gtk_notebook_get_current_page( notebook
);
258 if (i
< 0) return (wxMDIChildFrame
*) NULL
;
260 GtkNotebookPage
* page
= (GtkNotebookPage
*) (g_list_nth(notebook
->children
,i
)->data
);
261 if (!page
) return (wxMDIChildFrame
*) NULL
;
263 wxWindowList::compatibility_iterator node
= m_clientWindow
->GetChildren().GetFirst();
266 wxMDIChildFrame
*child_frame
= wxDynamicCast( node
->GetData(), wxMDIChildFrame
);
268 wxASSERT_MSG( child_frame
, _T("child is not a wxMDIChildFrame") );
270 if (child_frame
->m_page
== page
)
272 node
= node
->GetNext();
275 return (wxMDIChildFrame
*) NULL
;
278 wxMDIClientWindow
*wxMDIParentFrame::GetClientWindow() const
280 return m_clientWindow
;
283 wxMDIClientWindow
*wxMDIParentFrame::OnCreateClient()
285 m_clientWindow
= new wxMDIClientWindow( this );
286 return m_clientWindow
;
289 void wxMDIParentFrame::ActivateNext()
292 gtk_notebook_next_page( GTK_NOTEBOOK(m_clientWindow
->m_widget
) );
295 void wxMDIParentFrame::ActivatePrevious()
298 gtk_notebook_prev_page( GTK_NOTEBOOK(m_clientWindow
->m_widget
) );
301 //-----------------------------------------------------------------------------
303 //-----------------------------------------------------------------------------
305 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame
,wxFrame
)
307 BEGIN_EVENT_TABLE(wxMDIChildFrame
, wxFrame
)
308 EVT_ACTIVATE(wxMDIChildFrame::OnActivate
)
309 EVT_MENU_HIGHLIGHT_ALL(wxMDIChildFrame::OnMenuHighlight
)
312 wxMDIChildFrame::wxMDIChildFrame()
314 m_menuBar
= (wxMenuBar
*) NULL
;
315 m_page
= (GtkNotebookPage
*) NULL
;
318 wxMDIChildFrame::wxMDIChildFrame( wxMDIParentFrame
*parent
,
319 wxWindowID id
, const wxString
& title
,
320 const wxPoint
& WXUNUSED(pos
), const wxSize
& size
,
321 long style
, const wxString
& name
)
323 m_menuBar
= (wxMenuBar
*) NULL
;
324 m_page
= (GtkNotebookPage
*) NULL
;
325 Create( parent
, id
, title
, wxDefaultPosition
, size
, style
, name
);
328 wxMDIChildFrame::~wxMDIChildFrame()
334 bool wxMDIChildFrame::Create( wxMDIParentFrame
*parent
,
335 wxWindowID id
, const wxString
& title
,
336 const wxPoint
& WXUNUSED(pos
), const wxSize
& size
,
337 long style
, const wxString
& name
)
341 return wxWindow::Create( parent
->GetClientWindow(), id
, wxDefaultPosition
, size
, style
, name
);
344 void wxMDIChildFrame::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
346 wxWindow::DoSetSize( x
, y
, width
, height
, sizeFlags
);
349 void wxMDIChildFrame::DoSetClientSize(int width
, int height
)
351 wxWindow::DoSetClientSize( width
, height
);
354 void wxMDIChildFrame::DoGetClientSize( int *width
, int *height
) const
356 wxWindow::DoGetClientSize( width
, height
);
359 void wxMDIChildFrame::AddChild( wxWindowBase
*child
)
361 wxWindow::AddChild(child
);
364 void wxMDIChildFrame::SetMenuBar( wxMenuBar
*menu_bar
)
366 wxASSERT_MSG( m_menuBar
== NULL
, wxT("Only one menubar allowed") );
368 m_menuBar
= menu_bar
;
372 wxMDIParentFrame
*mdi_frame
= (wxMDIParentFrame
*)m_parent
->GetParent();
374 m_menuBar
->SetParent( mdi_frame
);
376 /* insert the invisible menu bar into the _parent_ mdi frame */
377 gtk_pizza_put( GTK_PIZZA(mdi_frame
->m_mainWidget
),
379 0, 0, mdi_frame
->m_width
, wxMENU_HEIGHT
);
383 wxMenuBar
*wxMDIChildFrame::GetMenuBar() const
388 void wxMDIChildFrame::Activate()
390 wxMDIParentFrame
* parent
= (wxMDIParentFrame
*) GetParent();
391 GtkNotebook
* notebook
= GTK_NOTEBOOK(parent
->m_widget
);
392 gint pageno
= gtk_notebook_page_num( notebook
, m_widget
);
393 gtk_notebook_set_page( notebook
, pageno
);
396 void wxMDIChildFrame::OnActivate( wxActivateEvent
& WXUNUSED(event
) )
400 void wxMDIChildFrame::OnMenuHighlight( wxMenuEvent
& event
)
403 wxMDIParentFrame
*mdi_frame
= (wxMDIParentFrame
*)m_parent
->GetParent();
404 if ( !ShowMenuHelp(mdi_frame
->GetStatusBar(), event
.GetMenuId()) )
406 // we don't have any help text for this item, but may be the MDI frame
408 mdi_frame
->OnMenuHighlight(event
);
410 #endif // wxUSE_STATUSBAR
413 void wxMDIChildFrame::SetTitle( const wxString
&title
)
415 if ( title
== m_title
)
420 wxMDIParentFrame
* parent
= (wxMDIParentFrame
*) GetParent();
421 GtkNotebook
* notebook
= GTK_NOTEBOOK(parent
->m_widget
);
422 gtk_notebook_set_tab_label_text(notebook
, m_widget
, wxGTK_CONV( title
) );
425 //-----------------------------------------------------------------------------
427 //-----------------------------------------------------------------------------
429 static void gtk_page_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxWindow
*win
)
431 if (g_isIdle
) wxapp_install_idle_handler();
433 if ((win
->m_x
== alloc
->x
) &&
434 (win
->m_y
== alloc
->y
) &&
435 (win
->m_width
== alloc
->width
) &&
436 (win
->m_height
== alloc
->height
) &&
442 win
->SetSize( alloc
->x
, alloc
->y
, alloc
->width
, alloc
->height
);
445 //-----------------------------------------------------------------------------
446 // InsertChild callback for wxMDIClientWindow
447 //-----------------------------------------------------------------------------
449 static void wxInsertChildInMDI( wxMDIClientWindow
* parent
, wxMDIChildFrame
* child
)
451 wxString s
= child
->m_title
;
452 if (s
.IsNull()) s
= _("MDI child");
454 GtkWidget
*label_widget
= gtk_label_new( s
.mbc_str() );
455 gtk_misc_set_alignment( GTK_MISC(label_widget
), 0.0, 0.5 );
457 gtk_signal_connect( GTK_OBJECT(child
->m_widget
), "size_allocate",
458 GTK_SIGNAL_FUNC(gtk_page_size_callback
), (gpointer
)child
);
460 GtkNotebook
*notebook
= GTK_NOTEBOOK(parent
->m_widget
);
462 gtk_notebook_append_page( notebook
, child
->m_widget
, label_widget
);
464 child
->m_page
= (GtkNotebookPage
*) (g_list_last(notebook
->children
)->data
);
466 wxMDIParentFrame
*parent_frame
= (wxMDIParentFrame
*) parent
->GetParent();
467 parent_frame
->m_justInserted
= true;
470 //-----------------------------------------------------------------------------
472 //-----------------------------------------------------------------------------
474 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow
,wxWindow
)
476 wxMDIClientWindow::wxMDIClientWindow()
480 wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame
*parent
, long style
)
482 CreateClient( parent
, style
);
485 wxMDIClientWindow::~wxMDIClientWindow()
489 bool wxMDIClientWindow::CreateClient( wxMDIParentFrame
*parent
, long style
)
493 m_insertCallback
= (wxInsertChildFunction
)wxInsertChildInMDI
;
495 if (!PreCreation( parent
, wxDefaultPosition
, wxDefaultSize
) ||
496 !CreateBase( parent
, -1, wxDefaultPosition
, wxDefaultSize
, style
, wxDefaultValidator
, wxT("wxMDIClientWindow") ))
498 wxFAIL_MSG( wxT("wxMDIClientWindow creation failed") );
502 m_widget
= gtk_notebook_new();
504 gtk_signal_connect( GTK_OBJECT(m_widget
), "switch_page",
505 GTK_SIGNAL_FUNC(gtk_mdi_page_change_callback
), (gpointer
)parent
);
507 gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget
), 1 );
509 m_parent
->DoAddChild( this );