1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/mdig.cpp
3 // Purpose: Generic MDI (Multiple Document Interface) classes
4 // Author: Hans Van Leemputten
5 // Modified by: Benjamin I. Williams / Kirix Corporation
8 // Copyright: (c) Hans Van Leemputten
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
29 #include "wx/settings.h"
30 #include "wx/aui/tabmdi.h"
39 #include "wx/stockitem.h"
49 //-----------------------------------------------------------------------------
50 // wxTabMDIParentFrame
51 //-----------------------------------------------------------------------------
53 IMPLEMENT_DYNAMIC_CLASS(wxTabMDIParentFrame
, wxFrame
)
55 BEGIN_EVENT_TABLE(wxTabMDIParentFrame
, wxFrame
)
57 EVT_MENU (wxID_ANY
, wxTabMDIParentFrame::DoHandleMenu
)
61 wxTabMDIParentFrame::wxTabMDIParentFrame()
66 wxTabMDIParentFrame::wxTabMDIParentFrame(wxWindow
*parent
,
68 const wxString
& title
,
75 (void)Create(parent
, id
, title
, pos
, size
, style
, name
);
78 wxTabMDIParentFrame::~wxTabMDIParentFrame()
80 // Make sure the client window is destructed before the menu bars are!
81 wxDELETE(m_pClientWindow
);
84 RemoveWindowMenu(GetMenuBar());
89 bool wxTabMDIParentFrame::Create(wxWindow
*parent
,
91 const wxString
& title
,
98 // this style can be used to prevent a window from having the standard MDI
100 if (!(style
& wxFRAME_NO_WINDOW_MENU
))
102 m_pWindowMenu
= new wxMenu
;
103 m_pWindowMenu
->Append(wxWINDOWCLOSE
, _("Cl&ose"));
104 m_pWindowMenu
->Append(wxWINDOWCLOSEALL
, _("Close All"));
105 m_pWindowMenu
->AppendSeparator();
106 m_pWindowMenu
->Append(wxWINDOWNEXT
, _("&Next"));
107 m_pWindowMenu
->Append(wxWINDOWPREV
, _("&Previous"));
109 #endif // wxUSE_MENUS
111 wxFrame::Create(parent
, id
, title
, pos
, size
, style
, name
);
117 void wxTabMDIParentFrame::SetWindowMenu(wxMenu
* pMenu
)
119 // Replace the window menu from the currently loaded menu bar.
120 wxMenuBar
*pMenuBar
= GetMenuBar();
124 RemoveWindowMenu(pMenuBar
);
125 wxDELETE(m_pWindowMenu
);
130 m_pWindowMenu
= pMenu
;
131 AddWindowMenu(pMenuBar
);
135 void wxTabMDIParentFrame::SetMenuBar(wxMenuBar
*pMenuBar
)
137 // Remove the Window menu from the old menu bar
138 RemoveWindowMenu(GetMenuBar());
140 // Add the Window menu to the new menu bar.
141 AddWindowMenu(pMenuBar
);
143 wxFrame::SetMenuBar(pMenuBar
);
144 m_pMyMenuBar
= GetMenuBar();
146 #endif // wxUSE_MENUS
148 void wxTabMDIParentFrame::SetChildMenuBar(wxTabMDIChildFrame
* pChild
)
153 // No Child, set Our menu bar back.
154 SetMenuBar(m_pMyMenuBar
);
156 // Make sure we know our menu bar is in use
161 if (pChild
->GetMenuBar() == NULL
)
164 // Do we need to save the current bar?
165 if (m_pMyMenuBar
== NULL
)
166 m_pMyMenuBar
= GetMenuBar();
168 SetMenuBar(pChild
->GetMenuBar());
170 #endif // wxUSE_MENUS
173 bool wxTabMDIParentFrame::ProcessEvent(wxEvent
& event
)
175 // Stops the same event being processed repeatedly
176 static wxEventType inEvent
= wxEVT_NULL
;
177 if (inEvent
== event
.GetEventType())
180 inEvent
= event
.GetEventType();
182 // Let the active child (if any) process the event first.
184 if (m_pActiveChild
&&
185 event
.IsCommandEvent() &&
186 event
.GetEventObject() != m_pClientWindow
&&
187 !(event
.GetEventType() == wxEVT_ACTIVATE
||
188 event
.GetEventType() == wxEVT_SET_FOCUS
||
189 event
.GetEventType() == wxEVT_KILL_FOCUS
||
190 event
.GetEventType() == wxEVT_CHILD_FOCUS
||
191 event
.GetEventType() == wxEVT_COMMAND_SET_FOCUS
||
192 event
.GetEventType() == wxEVT_COMMAND_KILL_FOCUS
)
195 res
= m_pActiveChild
->GetEventHandler()->ProcessEvent(event
);
198 // If the event was not handled this frame will handle it!
201 //res = GetEventHandler()->ProcessEvent(event);
202 res
= wxEvtHandler::ProcessEvent(event
);
205 inEvent
= wxEVT_NULL
;
210 wxTabMDIChildFrame
*wxTabMDIParentFrame::GetActiveChild() const
212 return m_pActiveChild
;
215 void wxTabMDIParentFrame::SetActiveChild(wxTabMDIChildFrame
* pChildFrame
)
217 m_pActiveChild
= pChildFrame
;
220 wxTabMDIClientWindow
*wxTabMDIParentFrame::GetClientWindow() const
222 return m_pClientWindow
;
225 wxTabMDIClientWindow
*wxTabMDIParentFrame::OnCreateClient()
227 m_pClientWindow
= new wxTabMDIClientWindow( this );
228 return m_pClientWindow
;
231 void wxTabMDIParentFrame::ActivateNext()
233 if (m_pClientWindow
&& m_pClientWindow
->GetSelection() != -1)
235 size_t active
= m_pClientWindow
->GetSelection() + 1;
236 if (active
>= m_pClientWindow
->GetPageCount())
239 m_pClientWindow
->SetSelection(active
);
243 void wxTabMDIParentFrame::ActivatePrevious()
245 if (m_pClientWindow
&& m_pClientWindow
->GetSelection() != -1)
247 int active
= m_pClientWindow
->GetSelection() - 1;
249 active
= m_pClientWindow
->GetPageCount() - 1;
251 m_pClientWindow
->SetSelection(active
);
255 void wxTabMDIParentFrame::Init()
257 m_pClientWindow
= NULL
;
258 m_pActiveChild
= NULL
;
260 m_pWindowMenu
= NULL
;
262 #endif // wxUSE_MENUS
266 void wxTabMDIParentFrame::RemoveWindowMenu(wxMenuBar
* pMenuBar
)
268 if (pMenuBar
&& m_pWindowMenu
)
270 // Remove old window menu
271 int pos
= pMenuBar
->FindMenu(_("&Window"));
272 if (pos
!= wxNOT_FOUND
)
274 // DBG:: We're going to delete the wrong menu!!!
275 wxASSERT(m_pWindowMenu
== pMenuBar
->GetMenu(pos
));
276 pMenuBar
->Remove(pos
);
281 void wxTabMDIParentFrame::AddWindowMenu(wxMenuBar
*pMenuBar
)
283 if (pMenuBar
&& m_pWindowMenu
)
285 int pos
= pMenuBar
->FindMenu(wxGetStockLabel(wxID_HELP
,false));
286 if (pos
== wxNOT_FOUND
)
287 pMenuBar
->Append(m_pWindowMenu
, _("&Window"));
289 pMenuBar
->Insert(pos
, m_pWindowMenu
, _("&Window"));
293 void wxTabMDIParentFrame::DoHandleMenu(wxCommandEvent
& event
)
295 switch (event
.GetId())
299 m_pActiveChild
->Close();
301 case wxWINDOWCLOSEALL
:
302 while (m_pActiveChild
)
304 if (!m_pActiveChild
->Close())
310 delete m_pActiveChild
;
311 m_pActiveChild
= NULL
;
325 #endif // wxUSE_MENUS
327 void wxTabMDIParentFrame::DoGetClientSize(int* width
, int* height
) const
329 wxFrame::DoGetClientSize(width
, height
);
332 //-----------------------------------------------------------------------------
333 // wxTabMDIChildFrame
334 //-----------------------------------------------------------------------------
336 IMPLEMENT_DYNAMIC_CLASS(wxTabMDIChildFrame
, wxPanel
)
338 BEGIN_EVENT_TABLE(wxTabMDIChildFrame
, wxPanel
)
339 EVT_MENU_HIGHLIGHT_ALL(wxTabMDIChildFrame::OnMenuHighlight
)
340 EVT_ACTIVATE(wxTabMDIChildFrame::OnActivate
)
341 EVT_CLOSE(wxTabMDIChildFrame::OnCloseWindow
)
344 wxTabMDIChildFrame::wxTabMDIChildFrame()
349 wxTabMDIChildFrame::wxTabMDIChildFrame(wxTabMDIParentFrame
*parent
,
351 const wxString
& title
,
352 const wxPoint
& WXUNUSED(pos
),
355 const wxString
& name
)
358 Create(parent
, id
, title
, wxDefaultPosition
, size
, style
, name
);
361 wxTabMDIChildFrame::~wxTabMDIChildFrame()
364 wxDELETE(m_pMenuBar
);
365 #endif // wxUSE_MENUS
368 bool wxTabMDIChildFrame::Create(wxTabMDIParentFrame
* parent
,
370 const wxString
& title
,
371 const wxPoint
& WXUNUSED(pos
),
374 const wxString
& name
)
376 wxTabMDIClientWindow
* pClientWindow
= parent
->GetClientWindow();
377 wxASSERT_MSG((pClientWindow
!= (wxWindow
*) NULL
), wxT("Missing MDI client window."));
379 wxPanel::Create(pClientWindow
, id
, wxDefaultPosition
, size
, style
|wxNO_BORDER
, name
);
381 SetMDIParentFrame(parent
);
383 // this is the currently active child
384 parent
->SetActiveChild(this);
388 pClientWindow
->AddPage(this, title
, true);
389 pClientWindow
->Refresh();
394 bool wxTabMDIChildFrame::Destroy()
396 wxTabMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
397 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
399 wxTabMDIClientWindow
* pClientWindow
= pParentFrame
->GetClientWindow();
400 wxASSERT_MSG(pClientWindow
, wxT("Missing MDI Client Window"));
402 bool bActive
= false;
403 if (pParentFrame
->GetActiveChild() == this)
405 pParentFrame
->SetActiveChild(NULL
);
406 pParentFrame
->SetChildMenuBar(NULL
);
410 size_t pos
, page_count
= pClientWindow
->GetPageCount();
411 for (pos
= 0; pos
< page_count
; pos
++)
413 if (pClientWindow
->GetPage(pos
) == this)
414 return pClientWindow
->DeletePage(pos
);
421 wxTabMDIParentFrame* pParentFrame = GetMDIParentFrame();
422 wxASSERT_MSG(pParentFrame, wxT("Missing MDI Parent Frame"));
424 bool bActive = false;
425 if (pParentFrame->GetActiveChild() == this)
427 pParentFrame->SetActiveChild(NULL);
428 pParentFrame->SetChildMenuBar(NULL);
432 wxTabMDIClientWindow* pClientWindow = pParentFrame->GetClientWindow();
434 // remove page if it is still there
436 for (pos = 0; pos < pClientWindow->GetPageCount(); pos++)
438 if (pClientWindow->GetPage(pos) == this)
440 if (pClientWindow->RemovePage(pos))
441 pClientWindow->Refresh();
448 // Set the new selection to the a remaining page
449 if (pos < pClientWindow->GetPageCount())
451 pClientWindow->SetSelection(pos);
455 if (pClientWindow->GetPageCount() >= 1)
456 pClientWindow->SetSelection(pClientWindow->GetPageCount() - 1);
460 // delete the child frame with pending delete, as is
461 // customary with frame windows
462 if (!wxPendingDelete.Member(this))
463 wxPendingDelete.Append(this);
470 void wxTabMDIChildFrame::SetMenuBar(wxMenuBar
*menu_bar
)
472 wxMenuBar
*pOldMenuBar
= m_pMenuBar
;
473 m_pMenuBar
= menu_bar
;
477 wxTabMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
478 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
480 m_pMenuBar
->SetParent(pParentFrame
);
481 if (pParentFrame
->GetActiveChild() == this)
483 // replace current menu bars
485 pParentFrame
->SetChildMenuBar(NULL
);
486 pParentFrame
->SetChildMenuBar(this);
491 wxMenuBar
*wxTabMDIChildFrame::GetMenuBar() const
495 #endif // wxUSE_MENUS
497 void wxTabMDIChildFrame::SetTitle(const wxString
& title
)
501 wxTabMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
502 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
504 wxTabMDIClientWindow
* pClientWindow
= pParentFrame
->GetClientWindow();
505 if (pClientWindow
!= NULL
)
508 for (pos
= 0; pos
< pClientWindow
->GetPageCount(); pos
++)
510 if (pClientWindow
->GetPage(pos
) == this)
512 pClientWindow
->SetPageText(pos
, m_title
);
519 wxString
wxTabMDIChildFrame::GetTitle() const
524 void wxTabMDIChildFrame::Activate()
526 wxTabMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
527 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
529 wxTabMDIClientWindow
* pClientWindow
= pParentFrame
->GetClientWindow();
531 if (pClientWindow
!= NULL
)
534 for (pos
= 0; pos
< pClientWindow
->GetPageCount(); pos
++)
536 if (pClientWindow
->GetPage(pos
) == this)
538 pClientWindow
->SetSelection(pos
);
545 void wxTabMDIChildFrame::OnMenuHighlight(wxMenuEvent
& event
)
548 if (m_pMDIParentFrame
)
550 // we don't have any help text for this item,
551 // but may be the MDI frame does?
552 m_pMDIParentFrame
->OnMenuHighlight(event
);
556 #endif // wxUSE_STATUSBAR
559 void wxTabMDIChildFrame::OnActivate(wxActivateEvent
& WXUNUSED(event
))
564 void wxTabMDIChildFrame::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
569 void wxTabMDIChildFrame::SetMDIParentFrame(wxTabMDIParentFrame
* parentFrame
)
571 m_pMDIParentFrame
= parentFrame
;
574 wxTabMDIParentFrame
* wxTabMDIChildFrame::GetMDIParentFrame() const
576 return m_pMDIParentFrame
;
579 void wxTabMDIChildFrame::Init()
581 m_pMDIParentFrame
= NULL
;
584 #endif // wxUSE_MENUS
587 bool wxTabMDIChildFrame::Show(bool WXUNUSED(show
))
593 void wxTabMDIChildFrame::DoShow(bool show
)
595 wxWindow::Show(show
);
598 void wxTabMDIChildFrame::DoSetSize(int x
, int y
, int width
, int height
, int WXUNUSED(sizeFlags
))
600 m_mdi_newrect
= wxRect(x
, y
, width
, height
);
603 void wxTabMDIChildFrame::DoMoveWindow(int x
, int y
, int width
, int height
)
605 m_mdi_newrect
= wxRect(x
, y
, width
, height
);
608 void wxTabMDIChildFrame::ApplyMDIChildFrameRect()
610 if (m_mdi_currect
!= m_mdi_newrect
)
612 wxPanel::DoMoveWindow(m_mdi_newrect
.x
, m_mdi_newrect
.y
,
613 m_mdi_newrect
.width
, m_mdi_newrect
.height
);
614 m_mdi_currect
= m_mdi_newrect
;
619 //-----------------------------------------------------------------------------
620 // wxTabMDIClientWindow
621 //-----------------------------------------------------------------------------
623 IMPLEMENT_DYNAMIC_CLASS(wxTabMDIClientWindow
, wxAuiMultiNotebook
)
625 BEGIN_EVENT_TABLE(wxTabMDIClientWindow
, wxAuiMultiNotebook
)
626 EVT_AUINOTEBOOK_PAGE_CHANGED(-1, wxTabMDIClientWindow::OnPageChanged
)
627 EVT_SIZE(wxTabMDIClientWindow::OnSize
)
630 wxTabMDIClientWindow::wxTabMDIClientWindow()
634 wxTabMDIClientWindow::wxTabMDIClientWindow(wxTabMDIParentFrame
* parent
, long style
)
636 CreateClient(parent
, style
);
639 wxTabMDIClientWindow::~wxTabMDIClientWindow()
644 bool wxTabMDIClientWindow::CreateClient(wxTabMDIParentFrame
* parent
, long style
)
646 SetWindowStyleFlag(style
);
648 if (!wxAuiMultiNotebook::Create(parent
,
657 wxColour bkcolour
= wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
);
658 SetBackgroundColour(bkcolour
);
660 m_mgr
.GetArtProvider()->SetColour(wxAUI_ART_BACKGROUND_COLOUR
, bkcolour
);
665 int wxTabMDIClientWindow::SetSelection(size_t nPage
)
667 return wxAuiMultiNotebook::SetSelection(nPage
);
670 void wxTabMDIClientWindow::PageChanged(int old_selection
, int new_selection
)
672 // don't do anything if the page doesn't actually change
673 if (old_selection
== new_selection
)
676 // don't do anything if the new page is already active
677 if (new_selection
!= -1)
679 wxTabMDIChildFrame
* child
= (wxTabMDIChildFrame
*)GetPage(new_selection
);
680 if (child
->GetMDIParentFrame()->GetActiveChild() == child
)
684 // notify old active child that it has been deactivated
685 if (old_selection
!= -1)
687 wxTabMDIChildFrame
* old_child
= (wxTabMDIChildFrame
*)GetPage(old_selection
);
688 wxASSERT_MSG(old_child
, wxT("wxTabMDIClientWindow::PageChanged - null page pointer"));
690 wxActivateEvent
event(wxEVT_ACTIVATE
, false, old_child
->GetId());
691 event
.SetEventObject(old_child
);
692 old_child
->GetEventHandler()->ProcessEvent(event
);
695 // notify new active child that it has been activated
696 if (new_selection
!= -1)
698 wxTabMDIChildFrame
* active_child
= (wxTabMDIChildFrame
*)GetPage(new_selection
);
699 wxASSERT_MSG(active_child
, wxT("wxTabMDIClientWindow::PageChanged - null page pointer"));
701 wxActivateEvent
event(wxEVT_ACTIVATE
, true, active_child
->GetId());
702 event
.SetEventObject(active_child
);
703 active_child
->GetEventHandler()->ProcessEvent(event
);
705 if (active_child
->GetMDIParentFrame())
707 active_child
->GetMDIParentFrame()->SetActiveChild(active_child
);
708 active_child
->GetMDIParentFrame()->SetChildMenuBar(active_child
);
713 void wxTabMDIClientWindow::OnPageChanged(wxAuiNotebookEvent
& evt
)
715 PageChanged(evt
.GetOldSelection(), evt
.GetSelection());
719 void wxTabMDIClientWindow::OnSize(wxSizeEvent
& evt
)
721 wxAuiMultiNotebook::OnSize(evt
);
723 for (size_t pos
= 0; pos
< GetPageCount(); pos
++)
724 ((wxTabMDIChildFrame
*)GetPage(pos
))->ApplyMDIChildFrameRect();