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
*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 BEGIN_EVENT_TABLE(wxMDIParentFrame
, wxFrame
)
106 wxMDIParentFrame::wxMDIParentFrame()
108 m_justInserted
= FALSE
;
109 m_clientWindow
= (wxMDIClientWindow
*) NULL
;
112 wxMDIParentFrame::wxMDIParentFrame( wxWindow
*parent
,
113 wxWindowID id
, const wxString
& title
,
114 const wxPoint
& pos
, const wxSize
& size
,
115 long style
, const wxString
& name
)
117 m_justInserted
= FALSE
;
118 m_clientWindow
= (wxMDIClientWindow
*) NULL
;
119 Create( parent
, id
, title
, pos
, size
, style
, name
);
122 wxMDIParentFrame::~wxMDIParentFrame()
126 bool wxMDIParentFrame::Create( wxWindow
*parent
,
127 wxWindowID id
, const wxString
& title
,
128 const wxPoint
& pos
, const wxSize
& size
,
129 long style
, const wxString
& name
)
131 wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name
);
138 void wxMDIParentFrame::GtkOnSize( int x
, int y
, int width
, int height
)
140 wxFrame::GtkOnSize( x
, y
, width
, height
);
142 wxMDIChildFrame
*child_frame
= GetActiveChild();
143 if (!child_frame
) return;
145 wxMenuBar
*menu_bar
= child_frame
->m_menuBar
;
146 if (!menu_bar
) return;
147 if (!menu_bar
->m_widget
) return;
151 menu_bar
->m_width
= m_width
;
152 menu_bar
->m_height
= wxMENU_HEIGHT
;
153 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
155 0, 0, m_width
, wxMENU_HEIGHT
);
158 void wxMDIParentFrame::OnInternalIdle()
160 /* if a an MDI child window has just been inserted
161 it has to be brought to the top in idle time. we
162 simply set the last notebook page active as new
163 pages can only be appended at the end */
167 GtkNotebook
*notebook
= GTK_NOTEBOOK(m_clientWindow
->m_widget
);
168 gtk_notebook_set_page( notebook
, g_list_length( notebook
->children
) - 1 );
170 m_justInserted
= FALSE
;
174 wxFrame::OnInternalIdle();
176 wxMDIChildFrame
*active_child_frame
= GetActiveChild();
177 bool visible_child_menu
= FALSE
;
179 wxNode
*node
= m_clientWindow
->GetChildren().First();
182 wxMDIChildFrame
*child_frame
= (wxMDIChildFrame
*)node
->Data();
183 wxMenuBar
*menu_bar
= child_frame
->m_menuBar
;
184 if (child_frame
->m_menuBar
)
186 if (child_frame
== active_child_frame
)
188 if (menu_bar
->Show(TRUE
))
190 menu_bar
->m_width
= m_width
;
191 menu_bar
->m_height
= wxMENU_HEIGHT
;
192 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
194 0, 0, m_width
, wxMENU_HEIGHT
);
195 menu_bar
->SetInvokingWindow( child_frame
);
197 visible_child_menu
= TRUE
;
201 if (menu_bar
->Show(FALSE
))
203 menu_bar
->UnsetInvokingWindow( child_frame
);
210 /* show/hide parent menu bar as required */
211 if ((m_frameMenuBar
) &&
212 (m_frameMenuBar
->IsShown() == visible_child_menu
))
214 if (visible_child_menu
)
216 m_frameMenuBar
->Show( FALSE
);
217 m_frameMenuBar
->UnsetInvokingWindow( this );
221 m_frameMenuBar
->Show( TRUE
);
222 m_frameMenuBar
->SetInvokingWindow( this );
224 m_frameMenuBar
->m_width
= m_width
;
225 m_frameMenuBar
->m_height
= wxMENU_HEIGHT
;
226 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
227 m_frameMenuBar
->m_widget
,
228 0, 0, m_width
, wxMENU_HEIGHT
);
233 void wxMDIParentFrame::GetClientSize(int *width
, int *height
) const
235 wxFrame::GetClientSize( width
, height
);
238 wxMDIChildFrame
*wxMDIParentFrame::GetActiveChild() const
240 if (!m_clientWindow
) return (wxMDIChildFrame
*) NULL
;
242 GtkNotebook
*notebook
= GTK_NOTEBOOK(m_clientWindow
->m_widget
);
243 if (!notebook
) return (wxMDIChildFrame
*) NULL
;
245 #if (GTK_MINOR_VERSION > 0)
246 gint i
= gtk_notebook_get_current_page( notebook
);
248 gint i
= gtk_notebook_current_page( notebook
);
250 if (i
< 0) return (wxMDIChildFrame
*) NULL
;
252 GtkNotebookPage
* page
= (GtkNotebookPage
*) (g_list_nth(notebook
->children
,i
)->data
);
253 if (!page
) return (wxMDIChildFrame
*) NULL
;
255 wxNode
*node
= m_clientWindow
->GetChildren().First();
258 wxMDIChildFrame
*child_frame
= (wxMDIChildFrame
*)node
->Data();
259 if (child_frame
->m_page
== page
)
264 return (wxMDIChildFrame
*) NULL
;
267 wxMDIClientWindow
*wxMDIParentFrame::GetClientWindow() const
269 return m_clientWindow
;
272 wxMDIClientWindow
*wxMDIParentFrame::OnCreateClient()
274 m_clientWindow
= new wxMDIClientWindow( this );
275 return m_clientWindow
;
278 void wxMDIParentFrame::ActivateNext()
281 gtk_notebook_next_page( GTK_NOTEBOOK(m_clientWindow
->m_widget
) );
284 void wxMDIParentFrame::ActivatePrevious()
287 gtk_notebook_prev_page( GTK_NOTEBOOK(m_clientWindow
->m_widget
) );
290 void wxMDIParentFrame::OnActivate( wxActivateEvent
& WXUNUSED(event
) )
294 void wxMDIParentFrame::OnSysColourChanged( wxSysColourChangedEvent
& WXUNUSED(event
) )
298 //-----------------------------------------------------------------------------
300 //-----------------------------------------------------------------------------
302 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame
,wxFrame
)
304 BEGIN_EVENT_TABLE(wxMDIChildFrame
, wxFrame
)
305 EVT_ACTIVATE(wxMDIChildFrame::OnActivate
)
308 wxMDIChildFrame::wxMDIChildFrame()
310 m_menuBar
= (wxMenuBar
*) NULL
;
311 m_page
= (GtkNotebookPage
*) NULL
;
314 wxMDIChildFrame::wxMDIChildFrame( wxMDIParentFrame
*parent
,
315 wxWindowID id
, const wxString
& title
,
316 const wxPoint
& WXUNUSED(pos
), const wxSize
& size
,
317 long style
, const wxString
& name
)
319 m_menuBar
= (wxMenuBar
*) NULL
;
320 m_page
= (GtkNotebookPage
*) NULL
;
321 Create( parent
, id
, title
, wxDefaultPosition
, size
, style
, name
);
324 wxMDIChildFrame::~wxMDIChildFrame()
330 bool wxMDIChildFrame::Create( wxMDIParentFrame
*parent
,
331 wxWindowID id
, const wxString
& title
,
332 const wxPoint
& WXUNUSED(pos
), const wxSize
& size
,
333 long style
, const wxString
& name
)
337 return wxWindow::Create( parent
->GetClientWindow(), id
, wxDefaultPosition
, size
, style
, name
);
340 void wxMDIChildFrame::GetClientSize( int *width
, int *height
) const
342 wxWindow::GetClientSize( width
, height
);
345 void wxMDIChildFrame::AddChild( wxWindowBase
*child
)
347 wxWindow::AddChild(child
);
350 void wxMDIChildFrame::SetMenuBar( wxMenuBar
*menu_bar
)
352 wxASSERT_MSG( m_menuBar
== NULL
, wxT("Only one menubar allowed") );
354 m_menuBar
= menu_bar
;
358 wxMDIParentFrame
*mdi_frame
= (wxMDIParentFrame
*)m_parent
->GetParent();
360 m_menuBar
->SetParent( mdi_frame
);
362 /* insert the invisible menu bar into the _parent_ mdi frame */
363 gtk_pizza_put( GTK_PIZZA(mdi_frame
->m_mainWidget
),
365 0, 0, mdi_frame
->m_width
, wxMENU_HEIGHT
);
369 wxMenuBar
*wxMDIChildFrame::GetMenuBar() const
374 void wxMDIChildFrame::Activate()
376 #if (GTK_MINOR_VERSION > 0)
377 wxMDIParentFrame
* parent
= (wxMDIParentFrame
*) GetParent();
378 GtkNotebook
* notebook
= GTK_NOTEBOOK(parent
->m_widget
);
379 gint pageno
= gtk_notebook_page_num( notebook
, m_page
->child
);
380 gtk_notebook_set_page( notebook
, pageno
);
382 // the only way I can see to do this under gtk+ 1.0.X would
383 // be to keep track of page numbers, start at first and
384 // do "next" enough times to get to this page number - messy
385 // - J. Russell Smyth
389 void wxMDIChildFrame::OnActivate( wxActivateEvent
&WXUNUSED(event
) )
393 //-----------------------------------------------------------------------------
395 //-----------------------------------------------------------------------------
397 static void gtk_page_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxWindow
*win
)
399 if (g_isIdle
) wxapp_install_idle_handler();
401 if ((win
->m_x
== alloc
->x
) &&
402 (win
->m_y
== alloc
->y
) &&
403 (win
->m_width
== alloc
->width
) &&
404 (win
->m_height
== alloc
->height
) &&
410 win
->SetSize( alloc
->x
, alloc
->y
, alloc
->width
, alloc
->height
);
413 //-----------------------------------------------------------------------------
414 // InsertChild callback for wxMDIClientWindow
415 //-----------------------------------------------------------------------------
417 static void wxInsertChildInMDI( wxMDIClientWindow
* parent
, wxMDIChildFrame
* child
)
419 wxString s
= child
->m_title
;
420 if (s
.IsNull()) s
= _("MDI child");
422 GtkWidget
*label_widget
= gtk_label_new( s
.mbc_str() );
423 gtk_misc_set_alignment( GTK_MISC(label_widget
), 0.0, 0.5 );
425 gtk_signal_connect( GTK_OBJECT(child
->m_widget
), "size_allocate",
426 GTK_SIGNAL_FUNC(gtk_page_size_callback
), (gpointer
)child
);
428 GtkNotebook
*notebook
= GTK_NOTEBOOK(parent
->m_widget
);
430 gtk_notebook_append_page( notebook
, child
->m_widget
, label_widget
);
432 child
->m_page
= (GtkNotebookPage
*) (g_list_last(notebook
->children
)->data
);
434 wxMDIParentFrame
*parent_frame
= (wxMDIParentFrame
*) parent
->GetParent();
435 parent_frame
->m_justInserted
= TRUE
;
438 //-----------------------------------------------------------------------------
440 //-----------------------------------------------------------------------------
442 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow
,wxWindow
)
444 wxMDIClientWindow::wxMDIClientWindow()
448 wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame
*parent
, long style
)
450 CreateClient( parent
, style
);
453 wxMDIClientWindow::~wxMDIClientWindow()
457 bool wxMDIClientWindow::CreateClient( wxMDIParentFrame
*parent
, long style
)
461 m_insertCallback
= (wxInsertChildFunction
)wxInsertChildInMDI
;
463 if (!PreCreation( parent
, wxDefaultPosition
, wxDefaultSize
) ||
464 !CreateBase( parent
, -1, wxDefaultPosition
, wxDefaultSize
, style
, wxDefaultValidator
, wxT("wxMDIClientWindow") ))
466 wxFAIL_MSG( wxT("wxMDIClientWindow creation failed") );
470 m_widget
= gtk_notebook_new();
472 gtk_signal_connect( GTK_OBJECT(m_widget
), "switch_page",
473 GTK_SIGNAL_FUNC(gtk_mdi_page_change_callback
), (gpointer
)parent
);
475 gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget
), 1 );
477 m_parent
->DoAddChild( this );