X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e0dc13d470f31c31f38927a2565b94cd126ddf9a..739c5499fcab1c165b8dd0591c9fd9e2329b3cf9:/src/aui/tabmdi.cpp diff --git a/src/aui/tabmdi.cpp b/src/aui/tabmdi.cpp index c216c63588..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,12 +80,15 @@ 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); #if wxUSE_MENUS + wxDELETE(m_pMyMenuBar); RemoveWindowMenu(GetMenuBar()); - delete m_pWindowMenu; + wxDELETE(m_pWindowMenu); #endif // wxUSE_MENUS } @@ -109,9 +114,11 @@ bool wxAuiMDIParentFrame::Create(wxWindow *parent, } #endif // wxUSE_MENUS - wxFrame::Create(parent, id, title, pos, size, style, name); - OnCreateClient(); - return true; + if ( !wxFrame::Create(parent, id, title, pos, size, style, name) ) + return false; + + m_pClientWindow = OnCreateClient(); + return m_pClientWindow != NULL; } @@ -127,7 +134,7 @@ wxAuiTabArt* wxAuiMDIParentFrame::GetArtProvider() { if (!m_pClientWindow) return NULL; - + return m_pClientWindow->GetArtProvider(); } @@ -166,7 +173,7 @@ void wxAuiMDIParentFrame::SetMenuBar(wxMenuBar* pMenuBar) AddWindowMenu(pMenuBar); wxFrame::SetMenuBar(pMenuBar); - m_pMyMenuBar = GetMenuBar(); + //m_pMyMenuBar = GetMenuBar(); } #endif // wxUSE_MENUS @@ -176,12 +183,15 @@ void wxAuiMDIParentFrame::SetChildMenuBar(wxAuiMDIChildFrame* pChild) if (!pChild) { // No Child, set Our menu bar back. - SetMenuBar(m_pMyMenuBar); + if (m_pMyMenuBar) + SetMenuBar(m_pMyMenuBar); + else + SetMenuBar(GetMenuBar()); // Make sure we know our menu bar is in use - //m_pMyMenuBar = NULL; + m_pMyMenuBar = NULL; } - else + else { if (pChild->GetMenuBar() == NULL) return; @@ -201,10 +211,11 @@ bool wxAuiMDIParentFrame::ProcessEvent(wxEvent& event) if (m_pLastEvt == &event) return false; m_pLastEvt = &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 || @@ -215,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) @@ -233,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 @@ -248,8 +266,7 @@ wxAuiMDIClientWindow *wxAuiMDIParentFrame::GetClientWindow() const wxAuiMDIClientWindow *wxAuiMDIParentFrame::OnCreateClient() { - m_pClientWindow = new wxAuiMDIClientWindow( this ); - return m_pClientWindow; + return new wxAuiMDIClientWindow( this ); } void wxAuiMDIParentFrame::ActivateNext() @@ -280,7 +297,6 @@ void wxAuiMDIParentFrame::Init() { m_pLastEvt = NULL; m_pClientWindow = NULL; - m_pActiveChild = NULL; #if wxUSE_MENUS m_pWindowMenu = NULL; m_pMyMenuBar = NULL; @@ -310,7 +326,7 @@ void wxAuiMDIParentFrame::AddWindowMenu(wxMenuBar *pMenuBar) int pos = pMenuBar->FindMenu(wxGetStockLabel(wxID_HELP,wxSTOCK_NOFLAGS)); if (pos == wxNOT_FOUND) pMenuBar->Append(m_pWindowMenu, _("&Window")); - else + else pMenuBar->Insert(pos, m_pWindowMenu, _("&Window")); } } @@ -320,23 +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 } - else - { - delete m_pActiveChild; - m_pActiveChild = NULL; - } } 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 @@ -354,6 +400,26 @@ void wxAuiMDIParentFrame::DoGetClientSize(int* width, int* height) const wxFrame::DoGetClientSize(width, height); } +void wxAuiMDIParentFrame::Tile(wxOrientation orient) +{ + wxAuiMDIClientWindow* client_window = GetClientWindow(); + wxASSERT_MSG(client_window, wxT("Missing MDI Client Window")); + + int cur_idx = client_window->GetSelection(); + if (cur_idx == -1) + return; + + if (orient == wxVERTICAL) + { + client_window->Split(cur_idx, wxLEFT); + } + else if (orient == wxHORIZONTAL) + { + client_window->Split(cur_idx, wxTOP); + } +} + + //----------------------------------------------------------------------------- // wxAuiMDIChildFrame //----------------------------------------------------------------------------- @@ -380,11 +446,39 @@ wxAuiMDIChildFrame::wxAuiMDIChildFrame(wxAuiMDIParentFrame *parent, const wxString& name) { Init(); - Create(parent, id, title, wxDefaultPosition, size, style, name); + + // There are two ways to create an tabbed mdi child fram without + // making it the active document. Either Show(false) can be called + // before Create() (as is customary on some ports with wxFrame-type + // windows), or wxMINIMIZE can be passed in the style flags. Note that + // wxAuiMDIChildFrame is not really derived from wxFrame, as wxMDIChildFrame + // is, but those are the expected symantics. No style flag is passed + // onto the panel underneath. + if (style & wxMINIMIZE) + m_activateOnCreate = false; + + Create(parent, id, title, wxDefaultPosition, size, 0, name); } wxAuiMDIChildFrame::~wxAuiMDIChildFrame() { + wxAuiMDIParentFrame* pParentFrame = GetMDIParentFrame(); + if (pParentFrame) + { + if (pParentFrame->GetActiveChild() == this) + { + pParentFrame->SetActiveChild(NULL); + pParentFrame->SetChildMenuBar(NULL); + } + wxAuiMDIClientWindow* pClientWindow = pParentFrame->GetClientWindow(); + wxASSERT(pClientWindow); + int idx = pClientWindow->GetPageIndex(this); + if (idx != wxNOT_FOUND) + { + pClientWindow->RemovePage(idx); + } + } + #if wxUSE_MENUS wxDELETE(m_pMenuBar); #endif // wxUSE_MENUS @@ -399,18 +493,40 @@ bool wxAuiMDIChildFrame::Create(wxAuiMDIParentFrame* parent, const wxString& name) { wxAuiMDIClientWindow* pClientWindow = parent->GetClientWindow(); - wxASSERT_MSG((pClientWindow != (wxWindow*) NULL), wxT("Missing MDI client window.")); + wxASSERT_MSG((pClientWindow != NULL), wxT("Missing MDI client window.")); - wxPanel::Create(pClientWindow, id, wxDefaultPosition, size, style|wxNO_BORDER, name); + // see comment in constructor + if (style & wxMINIMIZE) + m_activateOnCreate = false; - SetMDIParentFrame(parent); + wxSize cli_size = pClientWindow->GetClientSize(); + + // create the window off-screen to prevent flicker + wxPanel::Create(pClientWindow, + id, + wxPoint(cli_size.x+1, cli_size.y+1), + size, + wxNO_BORDER, name); - // this is the currently active child - parent->SetActiveChild(this); + DoShow(false); + + SetMDIParentFrame(parent); m_title = title; - pClientWindow->AddPage(this, title, true); + 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; @@ -426,11 +542,15 @@ bool wxAuiMDIChildFrame::Destroy() if (pParentFrame->GetActiveChild() == this) { - pParentFrame->SetActiveChild(NULL); + // deactivate ourself + wxActivateEvent event(wxEVT_ACTIVATE, false, GetId()); + event.SetEventObject(this); + GetEventHandler()->ProcessEvent(event); + pParentFrame->SetChildMenuBar(NULL); } - const size_t page_count = pClientWindow->GetPageCount(); + size_t page_count = pClientWindow->GetPageCount(); for (size_t pos = 0; pos < page_count; pos++) { if (pClientWindow->GetPage(pos) == this) @@ -499,12 +619,12 @@ void wxAuiMDIChildFrame::SetIcons(const wxIconBundle& icons) { // get icon with the system icon size SetIcon(icons.GetIcon(-1)); - m_icon_bundle = icons; + m_iconBundle = icons; } const wxIconBundle& wxAuiMDIChildFrame::GetIcons() const { - return m_icon_bundle; + return m_iconBundle; } void wxAuiMDIChildFrame::SetIcon(const wxIcon& icon) @@ -513,15 +633,15 @@ void wxAuiMDIChildFrame::SetIcon(const wxIcon& icon) wxASSERT_MSG(pParentFrame, wxT("Missing MDI Parent Frame")); m_icon = icon; - + wxBitmap bmp; bmp.CopyFromIcon(m_icon); - + wxAuiMDIClientWindow* pClientWindow = pParentFrame->GetClientWindow(); if (pClientWindow != NULL) { int idx = pClientWindow->GetPageIndex(this); - + if (idx != -1) { pClientWindow->SetPageBitmap((size_t)idx, bmp); @@ -533,8 +653,8 @@ const wxIcon& wxAuiMDIChildFrame::GetIcon() const { return m_icon; } - - + + void wxAuiMDIChildFrame::Activate() { wxAuiMDIParentFrame* pParentFrame = GetMDIParentFrame(); @@ -592,14 +712,25 @@ wxAuiMDIParentFrame* wxAuiMDIChildFrame::GetMDIParentFrame() const void wxAuiMDIChildFrame::Init() { + m_activateOnCreate = true; m_pMDIParentFrame = NULL; #if wxUSE_MENUS m_pMenuBar = NULL; #endif // wxUSE_MENUS } -bool wxAuiMDIChildFrame::Show(bool WXUNUSED(show)) +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 return true; } @@ -611,7 +742,7 @@ void wxAuiMDIChildFrame::DoShow(bool show) void wxAuiMDIChildFrame::DoSetSize(int x, int y, int width, int height, int sizeFlags) { - m_mdi_newrect = wxRect(x, y, width, height); + m_mdiNewRect = wxRect(x, y, width, height); #ifdef __WXGTK__ wxPanel::DoSetSize(x,y,width, height, sizeFlags); #else @@ -621,16 +752,16 @@ void wxAuiMDIChildFrame::DoSetSize(int x, int y, int width, int height, int size void wxAuiMDIChildFrame::DoMoveWindow(int x, int y, int width, int height) { - m_mdi_newrect = wxRect(x, y, width, height); + m_mdiNewRect = wxRect(x, y, width, height); } void wxAuiMDIChildFrame::ApplyMDIChildFrameRect() { - if (m_mdi_currect != m_mdi_newrect) + if (m_mdiCurRect != m_mdiNewRect) { - wxPanel::DoMoveWindow(m_mdi_newrect.x, m_mdi_newrect.y, - m_mdi_newrect.width, m_mdi_newrect.height); - m_mdi_currect = m_mdi_newrect; + wxPanel::DoMoveWindow(m_mdiNewRect.x, m_mdiNewRect.y, + m_mdiNewRect.width, m_mdiNewRect.height); + m_mdiCurRect = m_mdiNewRect; } } @@ -643,6 +774,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxAuiMDIClientWindow, wxAuiNotebook) BEGIN_EVENT_TABLE(wxAuiMDIClientWindow, wxAuiNotebook) EVT_AUINOTEBOOK_PAGE_CHANGED(wxID_ANY, wxAuiMDIClientWindow::OnPageChanged) + EVT_AUINOTEBOOK_PAGE_CLOSE(wxID_ANY, wxAuiMDIClientWindow::OnPageClose) EVT_SIZE(wxAuiMDIClientWindow::OnSize) END_EVENT_TABLE() @@ -655,15 +787,15 @@ wxAuiMDIClientWindow::wxAuiMDIClientWindow(wxAuiMDIParentFrame* parent, long sty CreateClient(parent, style); } -wxAuiMDIClientWindow::~wxAuiMDIClientWindow() -{ - DestroyChildren(); -} - bool wxAuiMDIClientWindow::CreateClient(wxAuiMDIParentFrame* parent, long style) { SetWindowStyleFlag(style); + wxSize caption_icon_size = + wxSize(wxSystemSettings::GetMetric(wxSYS_SMALLICON_X), + wxSystemSettings::GetMetric(wxSYS_SMALLICON_Y)); + SetUniformBitmapSize(caption_icon_size); + if (!wxAuiNotebook::Create(parent, wxID_ANY, wxPoint(0,0), @@ -674,9 +806,9 @@ bool wxAuiMDIClientWindow::CreateClient(wxAuiMDIParentFrame* parent, long style) } wxColour bkcolour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE); - SetBackgroundColour(bkcolour); + SetOwnBackgroundColour(bkcolour); - m_mgr.GetArtProvider()->SetColour(wxAUI_ART_BACKGROUND_COLOUR, bkcolour); + m_mgr.GetArtProvider()->SetColour(wxAUI_DOCKART_BACKGROUND_COLOUR, bkcolour); return true; } @@ -686,22 +818,33 @@ 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 if (old_selection == new_selection) return; + /* // don't do anything if the new page is already active if (new_selection != -1) { wxAuiMDIChildFrame* child = (wxAuiMDIChildFrame*)GetPage(new_selection); if (child->GetMDIParentFrame()->GetActiveChild() == child) return; - } + }*/ + // notify old active child that it has been deactivated - if (old_selection != -1) + if ((old_selection != -1) && (old_selection < (int)GetPageCount())) { wxAuiMDIChildFrame* old_child = (wxAuiMDIChildFrame*)GetPage(old_selection); wxASSERT_MSG(old_child, wxT("wxAuiMDIClientWindow::PageChanged - null page pointer")); @@ -727,12 +870,26 @@ void wxAuiMDIClientWindow::PageChanged(int old_selection, int new_selection) active_child->GetMDIParentFrame()->SetChildMenuBar(active_child); } } + + +} + +void wxAuiMDIClientWindow::OnPageClose(wxAuiNotebookEvent& evt) +{ + wxAuiMDIChildFrame* wnd; + wnd = static_cast<wxAuiMDIChildFrame*>(GetPage(evt.GetSelection())); + + wnd->Close(); + + // regardless of the result of wnd->Close(), we've + // already taken care of the close operations, so + // suppress further processing + evt.Veto(); } void wxAuiMDIClientWindow::OnPageChanged(wxAuiNotebookEvent& evt) { PageChanged(evt.GetOldSelection(), evt.GetSelection()); - evt.Skip(); } void wxAuiMDIClientWindow::OnSize(wxSizeEvent& evt)