X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9a29fe70bc90b08b4f0bd4c23c1d12ad17cbbed2..87f0b1323b7ac77f02133b836c8dfee63b0fd387:/src/aui/tabmdi.cpp diff --git a/src/aui/tabmdi.cpp b/src/aui/tabmdi.cpp index 2059d90941..edf19a97be 100644 --- a/src/aui/tabmdi.cpp +++ b/src/aui/tabmdi.cpp @@ -38,6 +38,7 @@ #endif //WX_PRECOMP #include "wx/stockitem.h" +#include "wx/aui/dockart.h" enum MDI_MENU_ID { @@ -56,6 +57,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxAuiMDIParentFrame, wxFrame) BEGIN_EVENT_TABLE(wxAuiMDIParentFrame, wxFrame) #if wxUSE_MENUS EVT_MENU (wxID_ANY, wxAuiMDIParentFrame::DoHandleMenu) + EVT_UPDATE_UI (wxID_ANY, wxAuiMDIParentFrame::DoHandleUpdateUI) #endif END_EVENT_TABLE() @@ -78,6 +80,8 @@ wxAuiMDIParentFrame::wxAuiMDIParentFrame(wxWindow *parent, wxAuiMDIParentFrame::~wxAuiMDIParentFrame() { + // Avoid having GetActiveChild() called after m_pClientWindow is destroyed + SendDestroyEvent(); // Make sure the client window is destructed before the menu bars are! wxDELETE(m_pClientWindow); @@ -210,7 +214,8 @@ bool wxAuiMDIParentFrame::ProcessEvent(wxEvent& event) // let the active child (if any) process the event first. bool res = false; - if (m_pActiveChild && + wxAuiMDIChildFrame* pActiveChild = GetActiveChild(); + if (pActiveChild && event.IsCommandEvent() && event.GetEventObject() != m_pClientWindow && !(event.GetEventType() == wxEVT_ACTIVATE || @@ -221,7 +226,7 @@ bool wxAuiMDIParentFrame::ProcessEvent(wxEvent& event) event.GetEventType() == wxEVT_COMMAND_KILL_FOCUS ) ) { - res = m_pActiveChild->GetEventHandler()->ProcessEvent(event); + res = pActiveChild->GetEventHandler()->ProcessEvent(event); } if (!res) @@ -239,12 +244,19 @@ bool wxAuiMDIParentFrame::ProcessEvent(wxEvent& event) wxAuiMDIChildFrame *wxAuiMDIParentFrame::GetActiveChild() const { - return m_pActiveChild; + // We can be called before the client window is created, so check for its + // existence. + wxAuiMDIClientWindow* const client = GetClientWindow(); + return client ? client->GetActiveChild() : NULL; } void wxAuiMDIParentFrame::SetActiveChild(wxAuiMDIChildFrame* pChildFrame) { - m_pActiveChild = pChildFrame; + wxAuiMDIClientWindow* const client = GetClientWindow(); + if (client && client->GetActiveChild() != pChildFrame) + { + client->SetActiveChild(pChildFrame); + } } wxAuiMDIClientWindow *wxAuiMDIParentFrame::GetClientWindow() const @@ -285,7 +297,6 @@ void wxAuiMDIParentFrame::Init() { m_pLastEvt = NULL; m_pClientWindow = NULL; - m_pActiveChild = NULL; #if wxUSE_MENUS m_pWindowMenu = NULL; m_pMyMenuBar = NULL; @@ -325,18 +336,24 @@ void wxAuiMDIParentFrame::DoHandleMenu(wxCommandEvent& event) switch (event.GetId()) { case wxWINDOWCLOSE: - if (m_pActiveChild) - m_pActiveChild->Close(); + { + wxAuiMDIChildFrame* pActiveChild = GetActiveChild(); + if (pActiveChild) + pActiveChild->Close(); break; + } case wxWINDOWCLOSEALL: - while (m_pActiveChild) + { + wxAuiMDIChildFrame* pActiveChild; + while ((pActiveChild = GetActiveChild()) != NULL) { - if (!m_pActiveChild->Close()) + if (!pActiveChild->Close()) { return; // failure } } break; + } case wxWINDOWNEXT: ActivateNext(); break; @@ -347,6 +364,35 @@ void wxAuiMDIParentFrame::DoHandleMenu(wxCommandEvent& event) event.Skip(); } } + +void wxAuiMDIParentFrame::DoHandleUpdateUI(wxUpdateUIEvent& event) +{ + switch (event.GetId()) + { + case wxWINDOWCLOSE: + case wxWINDOWCLOSEALL: + { + wxAuiMDIClientWindow* client_window = GetClientWindow(); + wxCHECK_RET(client_window, wxS("Missing MDI Client Window")); + size_t pages = client_window->GetPageCount(); + event.Enable(pages >= 1); + break; + } + + case wxWINDOWNEXT: + case wxWINDOWPREV: + { + wxAuiMDIClientWindow* client_window = GetClientWindow(); + wxCHECK_RET(client_window, wxS("Missing MDI Client Window")); + size_t pages = client_window->GetPageCount(); + event.Enable(pages >= 2); + break; + } + + default: + event.Skip(); + } +} #endif // wxUSE_MENUS void wxAuiMDIParentFrame::DoGetClientSize(int* width, int* height) const @@ -466,12 +512,21 @@ bool wxAuiMDIChildFrame::Create(wxAuiMDIParentFrame* parent, SetMDIParentFrame(parent); - // this is the currently active child - parent->SetActiveChild(this); - m_title = title; pClientWindow->AddPage(this, title, m_activateOnCreate); + + // Check that the parent notion of the active child coincides with our one. + // This is less obvious that it seems because we must honour + // m_activateOnCreate flag but only if it's not the first child because + // this one becomes active unconditionally. + wxASSERT_MSG + ( + (m_activateOnCreate || pClientWindow->GetPageCount() == 1) + == (parent->GetActiveChild() == this), + wxS("Logic error: child [not] activated when it should [not] have been.") + ); + pClientWindow->Refresh(); return true; @@ -492,7 +547,6 @@ bool wxAuiMDIChildFrame::Destroy() event.SetEventObject(this); GetEventHandler()->ProcessEvent(event); - pParentFrame->SetActiveChild(NULL); pParentFrame->SetChildMenuBar(NULL); } @@ -667,6 +721,14 @@ void wxAuiMDIChildFrame::Init() bool wxAuiMDIChildFrame::Show(bool show) { + // wxAuiMDIChildFrame uses m_activateOnCreate only to decide whether to + // activate the frame when it is created. After Create() is called, + // m_activateOnCreate will never be read again. Therefore, calling this + // function after Create() is pointless and you probably want to call + // Activate() instead. + wxCHECK_MSG( !GetHandle(), false, + wxS("Show() has no effect after Create(). Do you mean Activate()?") ); + m_activateOnCreate = show; // do nothing @@ -756,6 +818,15 @@ int wxAuiMDIClientWindow::SetSelection(size_t nPage) return wxAuiNotebook::SetSelection(nPage); } +wxAuiMDIChildFrame* wxAuiMDIClientWindow::GetActiveChild() +{ + const int sel = GetSelection(); + if ( sel == wxNOT_FOUND ) + return NULL; + + return wxStaticCast(GetPage(sel), wxAuiMDIChildFrame); +} + void wxAuiMDIClientWindow::PageChanged(int old_selection, int new_selection) { // don't do anything if the page doesn't actually change