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 //-----------------------------------------------------------------------------
50 static void gtk_mdi_page_change_callback(GtkNotebook
*WXUNUSED(widget
),
51 GtkNotebookPage
*WXUNUSED(page
),
53 wxMDIParentFrame
*parent
)
56 wxapp_install_idle_handler();
58 wxMDIChildFrame
*child
= parent
->GetActiveChild();
62 wxActivateEvent
event( wxEVT_ACTIVATE
, TRUE
, child
->GetId() );
63 event
.SetEventObject( child
);
64 child
->GetEventHandler()->ProcessEvent( event
);
67 //-----------------------------------------------------------------------------
69 //-----------------------------------------------------------------------------
71 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame
,wxFrame
)
73 BEGIN_EVENT_TABLE(wxMDIParentFrame
, wxFrame
)
76 wxMDIParentFrame::wxMDIParentFrame()
78 m_justInserted
= FALSE
;
79 m_clientWindow
= (wxMDIClientWindow
*) NULL
;
82 wxMDIParentFrame::wxMDIParentFrame( wxWindow
*parent
,
83 wxWindowID id
, const wxString
& title
,
84 const wxPoint
& pos
, const wxSize
& size
,
85 long style
, const wxString
& name
)
87 m_justInserted
= FALSE
;
88 m_clientWindow
= (wxMDIClientWindow
*) NULL
;
89 Create( parent
, id
, title
, pos
, size
, style
, name
);
92 wxMDIParentFrame::~wxMDIParentFrame()
96 bool wxMDIParentFrame::Create( wxWindow
*parent
,
97 wxWindowID id
, const wxString
& title
,
98 const wxPoint
& pos
, const wxSize
& size
,
99 long style
, const wxString
& name
)
101 wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name
);
108 void wxMDIParentFrame::GtkOnSize( int x
, int y
, int width
, int height
)
110 wxFrame::GtkOnSize( x
, y
, width
, height
);
112 wxMDIChildFrame
*child_frame
= GetActiveChild();
113 if (!child_frame
) return;
115 wxMenuBar
*menu_bar
= child_frame
->m_menuBar
;
116 if (!menu_bar
) return;
117 if (!menu_bar
->m_widget
) return;
121 menu_bar
->m_width
= m_width
;
122 menu_bar
->m_height
= wxMENU_HEIGHT
;
123 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
125 0, 0, m_width
, wxMENU_HEIGHT
);
128 void wxMDIParentFrame::OnInternalIdle()
130 /* if a an MDI child window has just been inserted
131 it has to be brought to the top in idle time. we
132 simply set the last notebook page active as new
133 pages can only be appended at the end */
137 GtkNotebook
*notebook
= GTK_NOTEBOOK(m_clientWindow
->m_widget
);
138 gtk_notebook_set_page( notebook
, g_list_length( notebook
->children
) - 1 );
140 m_justInserted
= FALSE
;
144 wxFrame::OnInternalIdle();
146 wxMDIChildFrame
*active_child_frame
= GetActiveChild();
147 bool visible_child_menu
= FALSE
;
149 wxNode
*node
= m_clientWindow
->GetChildren().First();
152 wxMDIChildFrame
*child_frame
= (wxMDIChildFrame
*)node
->Data();
153 wxMenuBar
*menu_bar
= child_frame
->m_menuBar
;
154 if (child_frame
->m_menuBar
)
156 if (child_frame
== active_child_frame
)
158 if (menu_bar
->Show(TRUE
))
160 menu_bar
->m_width
= m_width
;
161 menu_bar
->m_height
= wxMENU_HEIGHT
;
162 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
164 0, 0, m_width
, wxMENU_HEIGHT
);
165 menu_bar
->SetInvokingWindow( child_frame
);
167 visible_child_menu
= TRUE
;
171 if (menu_bar
->Show(FALSE
))
173 menu_bar
->UnsetInvokingWindow( child_frame
);
180 /* show/hide parent menu bar as required */
181 if ((m_frameMenuBar
) &&
182 (m_frameMenuBar
->IsShown() == visible_child_menu
))
184 if (visible_child_menu
)
186 m_frameMenuBar
->Show( FALSE
);
187 m_frameMenuBar
->UnsetInvokingWindow( this );
191 m_frameMenuBar
->Show( TRUE
);
192 m_frameMenuBar
->SetInvokingWindow( this );
194 m_frameMenuBar
->m_width
= m_width
;
195 m_frameMenuBar
->m_height
= wxMENU_HEIGHT
;
196 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
197 m_frameMenuBar
->m_widget
,
198 0, 0, m_width
, wxMENU_HEIGHT
);
203 void wxMDIParentFrame::GetClientSize(int *width
, int *height
) const
205 wxFrame::GetClientSize( width
, height
);
208 wxMDIChildFrame
*wxMDIParentFrame::GetActiveChild() const
210 if (!m_clientWindow
) return (wxMDIChildFrame
*) NULL
;
212 GtkNotebook
*notebook
= GTK_NOTEBOOK(m_clientWindow
->m_widget
);
213 if (!notebook
) return (wxMDIChildFrame
*) NULL
;
215 #if (GTK_MINOR_VERSION > 0)
216 gint i
= gtk_notebook_get_current_page( notebook
);
218 gint i
= gtk_notebook_current_page( notebook
);
220 if (i
< 0) return (wxMDIChildFrame
*) NULL
;
222 GtkNotebookPage
* page
= (GtkNotebookPage
*) (g_list_nth(notebook
->children
,i
)->data
);
223 if (!page
) return (wxMDIChildFrame
*) NULL
;
225 wxNode
*node
= m_clientWindow
->GetChildren().First();
228 wxMDIChildFrame
*child_frame
= (wxMDIChildFrame
*)node
->Data();
229 if (child_frame
->m_page
== page
)
234 return (wxMDIChildFrame
*) NULL
;
237 wxMDIClientWindow
*wxMDIParentFrame::GetClientWindow() const
239 return m_clientWindow
;
242 wxMDIClientWindow
*wxMDIParentFrame::OnCreateClient()
244 m_clientWindow
= new wxMDIClientWindow( this );
245 return m_clientWindow
;
248 void wxMDIParentFrame::ActivateNext()
251 gtk_notebook_next_page( GTK_NOTEBOOK(m_clientWindow
->m_widget
) );
254 void wxMDIParentFrame::ActivatePrevious()
257 gtk_notebook_prev_page( GTK_NOTEBOOK(m_clientWindow
->m_widget
) );
260 void wxMDIParentFrame::OnActivate( wxActivateEvent
& WXUNUSED(event
) )
264 void wxMDIParentFrame::OnSysColourChanged( wxSysColourChangedEvent
& WXUNUSED(event
) )
268 //-----------------------------------------------------------------------------
270 //-----------------------------------------------------------------------------
272 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame
,wxFrame
)
274 BEGIN_EVENT_TABLE(wxMDIChildFrame
, wxFrame
)
275 EVT_ACTIVATE(wxMDIChildFrame::OnActivate
)
278 wxMDIChildFrame::wxMDIChildFrame()
280 m_menuBar
= (wxMenuBar
*) NULL
;
281 m_page
= (GtkNotebookPage
*) NULL
;
284 wxMDIChildFrame::wxMDIChildFrame( wxMDIParentFrame
*parent
,
285 wxWindowID id
, const wxString
& title
,
286 const wxPoint
& WXUNUSED(pos
), const wxSize
& size
,
287 long style
, const wxString
& name
)
289 m_menuBar
= (wxMenuBar
*) NULL
;
290 m_page
= (GtkNotebookPage
*) NULL
;
291 Create( parent
, id
, title
, wxDefaultPosition
, size
, style
, name
);
294 wxMDIChildFrame::~wxMDIChildFrame()
300 bool wxMDIChildFrame::Create( wxMDIParentFrame
*parent
,
301 wxWindowID id
, const wxString
& title
,
302 const wxPoint
& WXUNUSED(pos
), const wxSize
& size
,
303 long style
, const wxString
& name
)
307 return wxWindow::Create( parent
->GetClientWindow(), id
, wxDefaultPosition
, size
, style
, name
);
310 void wxMDIChildFrame::GetClientSize( int *width
, int *height
) const
312 wxWindow::GetClientSize( width
, height
);
315 void wxMDIChildFrame::AddChild( wxWindowBase
*child
)
317 wxWindow::AddChild(child
);
320 void wxMDIChildFrame::SetMenuBar( wxMenuBar
*menu_bar
)
322 wxASSERT_MSG( m_menuBar
== NULL
, wxT("Only one menubar allowed") );
324 m_menuBar
= menu_bar
;
328 wxMDIParentFrame
*mdi_frame
= (wxMDIParentFrame
*)m_parent
->GetParent();
330 m_menuBar
->SetParent( mdi_frame
);
332 /* insert the invisible menu bar into the _parent_ mdi frame */
333 gtk_pizza_put( GTK_PIZZA(mdi_frame
->m_mainWidget
),
335 0, 0, mdi_frame
->m_width
, wxMENU_HEIGHT
);
339 wxMenuBar
*wxMDIChildFrame::GetMenuBar() const
344 void wxMDIChildFrame::Activate()
346 #if (GTK_MINOR_VERSION > 0)
347 wxMDIParentFrame
* parent
= (wxMDIParentFrame
*) GetParent();
348 GtkNotebook
* notebook
= GTK_NOTEBOOK(parent
->m_widget
);
349 gint pageno
= gtk_notebook_page_num( notebook
, m_page
->child
);
350 gtk_notebook_set_page( notebook
, pageno
);
352 // the only way I can see to do this under gtk+ 1.0.X would
353 // be to keep track of page numbers, start at first and
354 // do "next" enough times to get to this page number - messy
355 // - J. Russell Smyth
359 void wxMDIChildFrame::OnActivate( wxActivateEvent
&WXUNUSED(event
) )
363 //-----------------------------------------------------------------------------
365 //-----------------------------------------------------------------------------
367 static void gtk_page_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxWindow
*win
)
369 if (g_isIdle
) wxapp_install_idle_handler();
371 if ((win
->m_x
== alloc
->x
) &&
372 (win
->m_y
== alloc
->y
) &&
373 (win
->m_width
== alloc
->width
) &&
374 (win
->m_height
== alloc
->height
) &&
380 win
->SetSize( alloc
->x
, alloc
->y
, alloc
->width
, alloc
->height
);
383 //-----------------------------------------------------------------------------
384 // InsertChild callback for wxMDIClientWindow
385 //-----------------------------------------------------------------------------
387 static void wxInsertChildInMDI( wxMDIClientWindow
* parent
, wxMDIChildFrame
* child
)
389 wxString s
= child
->m_title
;
390 if (s
.IsNull()) s
= _("MDI child");
392 GtkWidget
*label_widget
= gtk_label_new( s
.mbc_str() );
393 gtk_misc_set_alignment( GTK_MISC(label_widget
), 0.0, 0.5 );
395 gtk_signal_connect( GTK_OBJECT(child
->m_widget
), "size_allocate",
396 GTK_SIGNAL_FUNC(gtk_page_size_callback
), (gpointer
)child
);
398 GtkNotebook
*notebook
= GTK_NOTEBOOK(parent
->m_widget
);
400 gtk_notebook_append_page( notebook
, child
->m_widget
, label_widget
);
402 child
->m_page
= (GtkNotebookPage
*) (g_list_last(notebook
->children
)->data
);
404 wxMDIParentFrame
*parent_frame
= (wxMDIParentFrame
*) parent
->GetParent();
405 parent_frame
->m_justInserted
= TRUE
;
408 //-----------------------------------------------------------------------------
410 //-----------------------------------------------------------------------------
412 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow
,wxWindow
)
414 wxMDIClientWindow::wxMDIClientWindow()
418 wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame
*parent
, long style
)
420 CreateClient( parent
, style
);
423 wxMDIClientWindow::~wxMDIClientWindow()
427 bool wxMDIClientWindow::CreateClient( wxMDIParentFrame
*parent
, long style
)
431 m_insertCallback
= (wxInsertChildFunction
)wxInsertChildInMDI
;
433 if (!PreCreation( parent
, wxDefaultPosition
, wxDefaultSize
) ||
434 !CreateBase( parent
, -1, wxDefaultPosition
, wxDefaultSize
, style
, wxDefaultValidator
, wxT("wxMDIClientWindow") ))
436 wxFAIL_MSG( wxT("wxMDIClientWindow creation failed") );
440 m_widget
= gtk_notebook_new();
442 gtk_signal_connect( GTK_OBJECT(m_widget
), "switch_page",
443 GTK_SIGNAL_FUNC(gtk_mdi_page_change_callback
), (gpointer
)parent
);
445 gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget
), 1 );
447 m_parent
->DoAddChild( this );