X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2997ca30d66c2dc778ed9a84c8c94fea6ec1c958..4f9ccec517819034d34d0b74a68659ccd6be272f:/src/generic/mdig.cpp diff --git a/src/generic/mdig.cpp b/src/generic/mdig.cpp index 8d33478b6d..d18b731a5f 100644 --- a/src/generic/mdig.cpp +++ b/src/generic/mdig.cpp @@ -2,10 +2,11 @@ // Name: src/generic/mdig.cpp // Purpose: Generic MDI (Multiple Document Interface) classes // Author: Hans Van Leemputten -// Modified by: +// Modified by: 2008-10-31 Vadim Zeitlin: derive from the base classes // Created: 29/07/2002 // RCS-ID: $Id$ -// Copyright: (c) Hans Van Leemputten +// Copyright: (c) 2002 Hans Van Leemputten +// (c) 2008 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -17,10 +18,6 @@ // headers // --------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "mdig.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -28,13 +25,20 @@ #pragma hdrstop #endif +#if wxUSE_MDI + #ifndef WX_PRECOMP - #include "wx/panel.h" #include "wx/menu.h" #include "wx/intl.h" + #include "wx/log.h" #endif //WX_PRECOMP +#include "wx/mdi.h" #include "wx/generic/mdig.h" +#include "wx/notebook.h" +#include "wx/scopeguard.h" + +#include "wx/stockitem.h" enum MDI_MENU_ID { @@ -51,48 +55,28 @@ enum MDI_MENU_ID IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIParentFrame, wxFrame) BEGIN_EVENT_TABLE(wxGenericMDIParentFrame, wxFrame) + EVT_CLOSE(wxGenericMDIParentFrame::OnClose) #if wxUSE_MENUS - EVT_MENU (wxID_ANY, wxGenericMDIParentFrame::DoHandleMenu) + EVT_MENU(wxID_ANY, wxGenericMDIParentFrame::OnWindowMenu) #endif END_EVENT_TABLE() -wxGenericMDIParentFrame::wxGenericMDIParentFrame() -{ - Init(); -} - -wxGenericMDIParentFrame::wxGenericMDIParentFrame(wxWindow *parent, - wxWindowID id, - const wxString& title, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) +void wxGenericMDIParentFrame::Init() { - Init(); - - (void)Create(parent, id, title, pos, size, style, name); +#if wxUSE_MENUS + m_pMyMenuBar = NULL; +#endif // wxUSE_MENUS } wxGenericMDIParentFrame::~wxGenericMDIParentFrame() { // Make sure the client window is destructed before the menu bars are! - wxDELETE(m_pClientWindow); + wxDELETE(m_clientWindow); #if wxUSE_MENUS - if (m_pMyMenuBar) - { - delete m_pMyMenuBar; - m_pMyMenuBar = (wxMenuBar *) NULL; - } + wxDELETE(m_pMyMenuBar); RemoveWindowMenu(GetMenuBar()); - - if (m_pWindowMenu) - { - delete m_pWindowMenu; - m_pWindowMenu = (wxMenu*) NULL; - } #endif // wxUSE_MENUS } @@ -104,26 +88,60 @@ bool wxGenericMDIParentFrame::Create(wxWindow *parent, long style, const wxString& name) { - // this style can be used to prevent a window from having the standard MDI - // "Window" menu - if ( !(style & wxFRAME_NO_WINDOW_MENU) ) - { + // this style can be used to prevent a window from having the standard MDI + // "Window" menu + if ( !(style & wxFRAME_NO_WINDOW_MENU) ) + { #if wxUSE_MENUS - m_pWindowMenu = new wxMenu; + m_windowMenu = new wxMenu; - m_pWindowMenu->Append(wxWINDOWCLOSE, _("Cl&ose")); - m_pWindowMenu->Append(wxWINDOWCLOSEALL, _("Close All")); - m_pWindowMenu->AppendSeparator(); - m_pWindowMenu->Append(wxWINDOWNEXT, _("&Next")); - m_pWindowMenu->Append(wxWINDOWPREV, _("&Previous")); + m_windowMenu->Append(wxWINDOWCLOSE, _("Cl&ose")); + m_windowMenu->Append(wxWINDOWCLOSEALL, _("Close All")); + m_windowMenu->AppendSeparator(); + m_windowMenu->Append(wxWINDOWNEXT, _("&Next")); + m_windowMenu->Append(wxWINDOWPREV, _("&Previous")); #endif // wxUSE_MENUS - } + } - wxFrame::Create( parent, id, title, pos, size, style, name ); + // the scrolling styles don't make sense neither for us nor for our client + // window (to which they're supposed to apply) + style &= ~(wxHSCROLL | wxVSCROLL); - OnCreateClient(); + if ( !wxFrame::Create( parent, id, title, pos, size, style, name ) ) + return false; + + wxGenericMDIClientWindow * const client = OnCreateGenericClient(); + if ( !client->CreateGenericClient(this) ) + return false; - return true; + m_clientWindow = client; + + return true; +} + +wxGenericMDIClientWindow *wxGenericMDIParentFrame::OnCreateGenericClient() +{ + return new wxGenericMDIClientWindow; +} + +bool wxGenericMDIParentFrame::CloseAll() +{ + wxGenericMDIClientWindow * const client = GetGenericClientWindow(); + if ( !client ) + return true; // none of the windows left + + wxBookCtrlBase * const book = client->GetBookCtrl(); + while ( book->GetPageCount() ) + { + wxGenericMDIChildFrame * const child = client->GetChild(0); + if ( !child->Close() ) + { + // it refused to close, don't close the remaining ones neither + return false; + } + } + + return true; } #if wxUSE_MENUS @@ -132,16 +150,16 @@ void wxGenericMDIParentFrame::SetWindowMenu(wxMenu* pMenu) // Replace the window menu from the currently loaded menu bar. wxMenuBar *pMenuBar = GetMenuBar(); - if (m_pWindowMenu) + if (m_windowMenu) { RemoveWindowMenu(pMenuBar); - wxDELETE(m_pWindowMenu); + wxDELETE(m_windowMenu); } if (pMenu) { - m_pWindowMenu = pMenu; + m_windowMenu = pMenu; AddWindowMenu(pMenuBar); } @@ -158,20 +176,20 @@ void wxGenericMDIParentFrame::SetMenuBar(wxMenuBar *pMenuBar) } #endif // wxUSE_MENUS -void wxGenericMDIParentFrame::SetChildMenuBar(wxGenericMDIChildFrame *pChild) +void wxGenericMDIParentFrame::WXSetChildMenuBar(wxGenericMDIChildFrame *pChild) { #if wxUSE_MENUS - if (pChild == (wxGenericMDIChildFrame *) NULL) + if (pChild == NULL) { // No Child, set Our menu bar back. SetMenuBar(m_pMyMenuBar); // Make sure we know our menu bar is in use - m_pMyMenuBar = (wxMenuBar*) NULL; + m_pMyMenuBar = NULL; } else { - if (pChild->GetMenuBar() == (wxMenuBar*) NULL) + if (pChild->GetMenuBar() == NULL) return; // Do we need to save the current bar? @@ -183,121 +201,101 @@ void wxGenericMDIParentFrame::SetChildMenuBar(wxGenericMDIChildFrame *pChild) #endif // wxUSE_MENUS } -bool wxGenericMDIParentFrame::ProcessEvent(wxEvent& event) +wxGenericMDIClientWindow * +wxGenericMDIParentFrame::GetGenericClientWindow() const { - /* - * Redirect events to active child first. - */ - - // Stops the same event being processed repeatedly - static wxEventType inEvent = wxEVT_NULL; - if (inEvent == event.GetEventType()) - return false; - - inEvent = event.GetEventType(); - - // Let the active child (if any) process the event first. - bool res = false; - if (m_pActiveChild && event.IsKindOf(CLASSINFO(wxCommandEvent)) -#if 0 - /* This is sure to not give problems... */ - && (event.GetEventType() == wxEVT_COMMAND_MENU_SELECTED || - event.GetEventType() == wxEVT_UPDATE_UI ) -#else - /* This was tested on wxMSW and worked... */ - && event.GetEventObject() != m_pClientWindow - && !(event.GetEventType() == wxEVT_ACTIVATE || - event.GetEventType() == wxEVT_SET_FOCUS || - event.GetEventType() == wxEVT_KILL_FOCUS || - event.GetEventType() == wxEVT_CHILD_FOCUS || - event.GetEventType() == wxEVT_COMMAND_SET_FOCUS || - event.GetEventType() == wxEVT_COMMAND_KILL_FOCUS ) -#endif - ) - { - res = m_pActiveChild->GetEventHandler()->ProcessEvent(event); - } - - // If the event was not handled this frame will handle it! - if (!res) - { - res = GetEventHandler()->wxEvtHandler::ProcessEvent(event); - } - - inEvent = wxEVT_NULL; - - return res; + return static_cast(m_clientWindow); } -wxGenericMDIChildFrame *wxGenericMDIParentFrame::GetActiveChild() const +wxBookCtrlBase *wxGenericMDIParentFrame::GetBookCtrl() const { - return m_pActiveChild; + wxGenericMDIClientWindow * const client = GetGenericClientWindow(); + return client ? client->GetBookCtrl() : NULL; } -void wxGenericMDIParentFrame::SetActiveChild(wxGenericMDIChildFrame* pChildFrame) +void wxGenericMDIParentFrame::AdvanceActive(bool forward) { - m_pActiveChild = pChildFrame; + wxBookCtrlBase * const book = GetBookCtrl(); + if ( book ) + book->AdvanceSelection(forward); } -wxGenericMDIClientWindow *wxGenericMDIParentFrame::GetClientWindow() const +void wxGenericMDIParentFrame::WXUpdateChildTitle(wxGenericMDIChildFrame *child) { - return m_pClientWindow; + wxGenericMDIClientWindow * const client = GetGenericClientWindow(); + + const int pos = client->FindChild(child); + if ( pos == wxNOT_FOUND ) + return; + + client->GetBookCtrl()->SetPageText(pos, child->GetTitle()); } -wxGenericMDIClientWindow *wxGenericMDIParentFrame::OnCreateClient() +void wxGenericMDIParentFrame::WXActivateChild(wxGenericMDIChildFrame *child) { -#if wxUSE_GENERIC_MDI_AS_NATIVE - m_pClientWindow = new wxMDIClientWindow( this ); -#else - m_pClientWindow = new wxGenericMDIClientWindow( this ); -#endif - return m_pClientWindow; + wxGenericMDIClientWindow * const client = GetGenericClientWindow(); + + const int pos = client->FindChild(child); + if ( pos == wxNOT_FOUND ) + return; + + client->GetBookCtrl()->SetSelection(pos); } -void wxGenericMDIParentFrame::ActivateNext() +void wxGenericMDIParentFrame::WXRemoveChild(wxGenericMDIChildFrame *child) { - if (m_pClientWindow && m_pClientWindow->GetSelection() != -1) + const bool removingActive = WXIsActiveChild(child); + if ( removingActive ) { - size_t active = m_pClientWindow->GetSelection() + 1; - if (active >= m_pClientWindow->GetPageCount()) - active = 0; - - m_pClientWindow->SetSelection(active); + SetActiveChild(NULL); + WXSetChildMenuBar(NULL); } -} -void wxGenericMDIParentFrame::ActivatePrevious() -{ - if (m_pClientWindow && m_pClientWindow->GetSelection() != -1) + wxGenericMDIClientWindow * const client = GetGenericClientWindow(); + wxCHECK_RET( client, "should have client window" ); + + wxBookCtrlBase * const book = client->GetBookCtrl(); + + // Remove page if still there + int pos = client->FindChild(child); + if ( pos != wxNOT_FOUND ) { - int active = m_pClientWindow->GetSelection() - 1; - if (active < 0) - active = m_pClientWindow->GetPageCount() - 1; + if ( book->RemovePage(pos) ) + book->Refresh(); + } - m_pClientWindow->SetSelection(active); + if ( removingActive ) + { + // Set the new selection to a remaining page + const size_t count = book->GetPageCount(); + if ( count > (size_t)pos ) + { + book->SetSelection(pos); + } + else + { + if ( count > 0 ) + book->SetSelection(count - 1); + } } } -void wxGenericMDIParentFrame::Init() +bool +wxGenericMDIParentFrame::WXIsActiveChild(wxGenericMDIChildFrame *child) const { - m_pClientWindow = (wxGenericMDIClientWindow *) NULL; - m_pActiveChild = (wxGenericMDIChildFrame *) NULL; -#if wxUSE_MENUS - m_pWindowMenu = (wxMenu *) NULL; - m_pMyMenuBar = (wxMenuBar*) NULL; -#endif // wxUSE_MENUS + return static_cast(GetActiveChild()) == child; } #if wxUSE_MENUS void wxGenericMDIParentFrame::RemoveWindowMenu(wxMenuBar *pMenuBar) { - if (pMenuBar && m_pWindowMenu) + if (pMenuBar && m_windowMenu) { // Remove old window menu int pos = pMenuBar->FindMenu(_("&Window")); if (pos != wxNOT_FOUND) { - wxASSERT(m_pWindowMenu == pMenuBar->GetMenu(pos)); // DBG:: We're going to delete the wrong menu!!! + wxASSERT(m_windowMenu == pMenuBar->GetMenu(pos)); // DBG:: We're going to delete the wrong menu!!! pMenuBar->Remove(pos); } } @@ -305,172 +303,144 @@ void wxGenericMDIParentFrame::RemoveWindowMenu(wxMenuBar *pMenuBar) void wxGenericMDIParentFrame::AddWindowMenu(wxMenuBar *pMenuBar) { - if (pMenuBar && m_pWindowMenu) + if (pMenuBar && m_windowMenu) { - int pos = pMenuBar->FindMenu(_("Help")); + int pos = pMenuBar->FindMenu(wxGetStockLabel(wxID_HELP,false)); if (pos == wxNOT_FOUND) { - pMenuBar->Append(m_pWindowMenu, _("&Window")); + pMenuBar->Append(m_windowMenu, _("&Window")); } else { - pMenuBar->Insert(pos, m_pWindowMenu, _("&Window")); + pMenuBar->Insert(pos, m_windowMenu, _("&Window")); } } } -void wxGenericMDIParentFrame::DoHandleMenu(wxCommandEvent &event) +void wxGenericMDIParentFrame::OnWindowMenu(wxCommandEvent &event) { - switch (event.GetId()) + switch ( event.GetId() ) { - case wxWINDOWCLOSE: - if (m_pActiveChild) - { - m_pActiveChild->Close(); - } - break; - case wxWINDOWCLOSEALL: - { -#if 0 // code is only needed if next #if is set to 0! - wxGenericMDIChildFrame *pFirstActiveChild = m_pActiveChild; -#endif - while (m_pActiveChild) - { - if (!m_pActiveChild->Close()) - { - return; // We failed... - } - else - { -#if 1 // What's best? Delayed deleting or immediate deleting? - delete m_pActiveChild; -#else - ActivateNext(); - - if (pFirstActiveChild == m_pActiveChild) - return; // We've called Close on all items, no need to continue. -#endif - } - } - } - break; - case wxWINDOWNEXT: - ActivateNext(); - break; - case wxWINDOWPREV: - ActivatePrevious(); - break; - default : - event.Skip(); + case wxWINDOWCLOSE: + if ( m_currentChild ) + m_currentChild->Close(); + break; + + case wxWINDOWCLOSEALL: + CloseAll(); + break; + + case wxWINDOWNEXT: + ActivateNext(); + break; + + case wxWINDOWPREV: + ActivatePrevious(); + break; + + default: + event.Skip(); } } #endif // wxUSE_MENUS -void wxGenericMDIParentFrame::DoGetClientSize(int *width, int *height) const +void wxGenericMDIParentFrame::OnClose(wxCloseEvent& event) { - wxFrame::DoGetClientSize( width, height ); + if ( !CloseAll() ) + event.Veto(); + else + event.Skip(); } +bool wxGenericMDIParentFrame::ProcessEvent(wxEvent& event) +{ + if ( m_currentChild ) + { + // the menu events should be given to the child as we show its menu bar + // as our own + const wxEventType eventType = event.GetEventType(); + if ( eventType == wxEVT_MENU || + eventType == wxEVT_UPDATE_UI ) + { + // set the flag indicating that this event was forwarded to the + // child from the parent and so shouldn't be propagated upwards if + // not processed to avoid infinite loop + m_childHandler = m_currentChild; + wxON_BLOCK_EXIT_NULL(m_childHandler); + + if ( m_currentChild->ProcessWindowEvent(event) ) + return true; + } + } -//----------------------------------------------------------------------------- + return wxMDIParentFrameBase::ProcessEvent(event); +} + +// ---------------------------------------------------------------------------- // wxGenericMDIChildFrame -//----------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIChildFrame, wxPanel) +IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIChildFrame, wxFrame) -BEGIN_EVENT_TABLE(wxGenericMDIChildFrame, wxPanel) +BEGIN_EVENT_TABLE(wxGenericMDIChildFrame, wxFrame) EVT_MENU_HIGHLIGHT_ALL(wxGenericMDIChildFrame::OnMenuHighlight) - EVT_ACTIVATE(wxGenericMDIChildFrame::OnActivate) - EVT_CLOSE(wxGenericMDIChildFrame::OnCloseWindow) - EVT_SIZE(wxGenericMDIChildFrame::OnSize) + EVT_CLOSE(wxGenericMDIChildFrame::OnClose) END_EVENT_TABLE() -wxGenericMDIChildFrame::wxGenericMDIChildFrame() -{ - Init(); -} - -wxGenericMDIChildFrame::wxGenericMDIChildFrame( wxGenericMDIParentFrame *parent, - wxWindowID id, const wxString& title, - const wxPoint& WXUNUSED(pos), const wxSize& size, - long style, const wxString& name ) +void wxGenericMDIChildFrame::Init() { - Init(); +#if wxUSE_MENUS + m_pMenuBar = NULL; +#endif // wxUSE_MENUS - Create( parent, id, title, wxDefaultPosition, size, style, name ); +#if !wxUSE_GENERIC_MDI_AS_NATIVE + m_mdiParentGeneric = NULL; +#endif } -#include "wx/log.h" wxGenericMDIChildFrame::~wxGenericMDIChildFrame() { - wxGenericMDIParentFrame *pParentFrame = GetMDIParentFrame(); + wxGenericMDIParentFrame * const parent = GetGenericMDIParent(); - if (pParentFrame != NULL) - { - bool bActive = false; - if (pParentFrame->GetActiveChild() == this) - { - pParentFrame->SetActiveChild((wxGenericMDIChildFrame*) NULL); - pParentFrame->SetChildMenuBar((wxGenericMDIChildFrame*) NULL); - bActive = true; - } - - wxGenericMDIClientWindow *pClientWindow = pParentFrame->GetClientWindow(); - - // Remove page if still there - size_t pos; - for (pos = 0; pos < pClientWindow->GetPageCount(); pos++) - { - if (pClientWindow->GetPage(pos) == this) - { - if (pClientWindow->RemovePage(pos)) - pClientWindow->Refresh(); - break; - } - } - - if (bActive) - { - // Set the new selection to the a remaining page - if (pClientWindow->GetPageCount() > pos) - { - pClientWindow->SetSelection(pos); - } - else - { - if ((int)pClientWindow->GetPageCount() - 1 >= 0) - pClientWindow->SetSelection(pClientWindow->GetPageCount() - 1); - } - } - } + // it could happen that we don't have a valid parent if we hadn't been ever + // really created -- but in this case there is nothing else to do neither + if ( parent ) + parent->WXRemoveChild(this); #if wxUSE_MENUS - wxDELETE(m_pMenuBar); + delete m_pMenuBar; #endif // wxUSE_MENUS } -bool wxGenericMDIChildFrame::Create( wxGenericMDIParentFrame *parent, - wxWindowID id, const wxString& title, - const wxPoint& WXUNUSED(pos), const wxSize& size, - long style, const wxString& name ) +bool wxGenericMDIChildFrame::Create(wxGenericMDIParentFrame *parent, + wxWindowID id, + const wxString& title, + const wxPoint& WXUNUSED(pos), + const wxSize& size, + long WXUNUSED(style), + const wxString& name) { - wxGenericMDIClientWindow* pClientWindow = parent->GetClientWindow(); - - wxASSERT_MSG((pClientWindow != (wxWindow*) NULL), wxT("Missing MDI client window.") ); - - wxPanel::Create(pClientWindow, id, wxDefaultPosition, size, style, name); + // unfortunately we can't use the base class m_mdiParent field unless + // wxGenericMDIParentFrame is wxMDIParentFrame +#if wxUSE_GENERIC_MDI_AS_NATIVE + m_mdiParent = parent; +#else // generic != native + // leave m_mdiParent NULL, we don't have it + m_mdiParentGeneric = parent; +#endif - SetMDIParentFrame(parent); + wxBookCtrlBase * const book = parent->GetBookCtrl(); - // This is the currently active child - parent->SetActiveChild(this); + wxASSERT_MSG( book, "Missing MDI client window." ); - m_Title = title; + // note that we ignore the styles, none of the usual TLW styles apply to + // this (child) window + if ( !wxWindow::Create(book, id, wxDefaultPosition, size, 0, name) ) + return false; - pClientWindow->AddPage(this, title, true); - ApplyMDIChildFrameRect(); // Ok confirme the size change! - pClientWindow->Refresh(); + m_title = title; + book->AddPage(this, title, true); return true; } @@ -483,18 +453,18 @@ void wxGenericMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar ) if (m_pMenuBar) { - wxGenericMDIParentFrame *pParentFrame = GetMDIParentFrame(); + wxGenericMDIParentFrame *parent = GetGenericMDIParent(); - if (pParentFrame != NULL) + if ( parent ) { - m_pMenuBar->SetParent(pParentFrame); + m_pMenuBar->SetParent(parent); - if (pParentFrame->GetActiveChild() == this) + if ( parent->WXIsActiveChild(this) ) { // Replace current menu bars if (pOldMenuBar) - pParentFrame->SetChildMenuBar((wxGenericMDIChildFrame*) NULL); - pParentFrame->SetChildMenuBar((wxGenericMDIChildFrame*) this); + parent->WXSetChildMenuBar(NULL); + parent->WXSetChildMenuBar(this); } } } @@ -508,245 +478,120 @@ wxMenuBar *wxGenericMDIChildFrame::GetMenuBar() const void wxGenericMDIChildFrame::SetTitle(const wxString& title) { - m_Title = title; - - wxGenericMDIParentFrame *pParentFrame = GetMDIParentFrame(); + m_title = title; - if (pParentFrame != NULL) - { - wxGenericMDIClientWindow * pClientWindow = pParentFrame->GetClientWindow(); - - if (pClientWindow != NULL) - { - size_t pos; - for (pos = 0; pos < pClientWindow->GetPageCount(); pos++) - { - if (pClientWindow->GetPage(pos) == this) - { - pClientWindow->SetPageText(pos, m_Title); - break; - } - } - } - } -} - -wxString wxGenericMDIChildFrame::GetTitle() const -{ - return m_Title; + wxGenericMDIParentFrame * const parent = GetGenericMDIParent(); + if ( parent ) + parent->WXUpdateChildTitle(this); + //else: it's ok, we might be not created yet } void wxGenericMDIChildFrame::Activate() { - wxGenericMDIParentFrame *pParentFrame = GetMDIParentFrame(); + wxGenericMDIParentFrame * const parent = GetGenericMDIParent(); - if (pParentFrame != NULL) - { - wxGenericMDIClientWindow * pClientWindow = pParentFrame->GetClientWindow(); - - if (pClientWindow != NULL) - { - size_t pos; - for (pos = 0; pos < pClientWindow->GetPageCount(); pos++) - { - if (pClientWindow->GetPage(pos) == this) - { - pClientWindow->SetSelection(pos); - break; - } - } - } - } + wxCHECK_RET( parent, "can't activate MDI child without parent" ); + parent->WXActivateChild(this); } void wxGenericMDIChildFrame::OnMenuHighlight(wxMenuEvent& event) { -#if wxUSE_STATUSBAR - if ( m_pMDIParentFrame) + wxGenericMDIParentFrame * const parent = GetGenericMDIParent(); + if ( parent) { // we don't have any help text for this item, // but may be the MDI frame does? - m_pMDIParentFrame->OnMenuHighlight(event); + parent->OnMenuHighlight(event); } -#else - wxUnusedVar(event); -#endif // wxUSE_STATUSBAR } -void wxGenericMDIChildFrame::OnActivate(wxActivateEvent& WXUNUSED(event)) +void wxGenericMDIChildFrame::OnClose(wxCloseEvent& WXUNUSED(event)) { - // Do mothing. + // we're not a TLW so don't delay the destruction of this window + delete this; } -/*** Copied from top level..! ***/ -// default resizing behaviour - if only ONE subwindow, resize to fill the -// whole client area -void wxGenericMDIChildFrame::OnSize(wxSizeEvent& WXUNUSED(event)) +bool wxGenericMDIChildFrame::TryAfter(wxEvent& event) { - // if we're using constraints or sizers - do use them - if ( GetAutoLayout() ) - { - Layout(); - } - else - { - // do we have _exactly_ one child? - wxWindow *child = (wxWindow *)NULL; - for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); - node; - node = node->GetNext() ) - { - wxWindow *win = node->GetData(); - - // exclude top level and managed windows (status bar isn't - // currently in the children list except under wxMac anyhow, but - // it makes no harm to test for it) - if ( !win->IsTopLevel() /*&& !IsOneOfBars(win)*/ ) - { - if ( child ) - { - return; // it's our second subwindow - nothing to do - } - - child = win; - } - } - - // do we have any children at all? - if ( child ) - { - // exactly one child - set it's size to fill the whole frame - int clientW, clientH; - DoGetClientSize(&clientW, &clientH); - - // for whatever reasons, wxGTK wants to have a small offset - it - // probably looks better with it? -#ifdef __WXGTK__ - static const int ofs = 1; -#else - static const int ofs = 0; -#endif - - child->SetSize(ofs, ofs, clientW - 2*ofs, clientH - 2*ofs); - } - } -} - -/*** Copied from top level..! ***/ -// The default implementation for the close window event. -void wxGenericMDIChildFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event)) -{ - Destroy(); -} - -void wxGenericMDIChildFrame::SetMDIParentFrame(wxGenericMDIParentFrame* parentFrame) -{ - m_pMDIParentFrame = parentFrame; -} - -wxGenericMDIParentFrame* wxGenericMDIChildFrame::GetMDIParentFrame() const -{ - return m_pMDIParentFrame; -} - -void wxGenericMDIChildFrame::Init() -{ - m_pMDIParentFrame = (wxGenericMDIParentFrame *) NULL; -#if wxUSE_MENUS - m_pMenuBar = (wxMenuBar *) NULL; -#endif // wxUSE_MENUS -} + // we shouldn't propagate the event to the parent if we received it from it + // in the first place + wxGenericMDIParentFrame * const parent = GetGenericMDIParent(); + if ( parent && parent->WXIsInsideChildHandler(this) ) + return false; -void wxGenericMDIChildFrame::DoMoveWindow(int x, int y, int width, int height) -{ - m_MDIRect = wxRect(x, y, width, height); + return wxTDIChildFrame::TryAfter(event); } -void wxGenericMDIChildFrame::ApplyMDIChildFrameRect() -{ - wxPanel::DoMoveWindow(m_MDIRect.x, m_MDIRect.y, m_MDIRect.width, m_MDIRect.height); -} - -//----------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- // wxGenericMDIClientWindow -//----------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- -#define wxID_NOTEBOOK_CLIENT_AREA wxID_HIGHEST + 100 +IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIClientWindow, wxWindow) -IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIClientWindow, wxNotebook) +bool +wxGenericMDIClientWindow::CreateGenericClient(wxWindow *parent) +{ + if ( !wxWindow::Create(parent, wxID_ANY) ) + return false; -BEGIN_EVENT_TABLE(wxGenericMDIClientWindow, wxNotebook) - EVT_NOTEBOOK_PAGE_CHANGED(wxID_NOTEBOOK_CLIENT_AREA, wxGenericMDIClientWindow::OnPageChanged) - EVT_SIZE(wxGenericMDIClientWindow::OnSize) -END_EVENT_TABLE() + m_notebook = new wxNotebook(this, wxID_ANY); + m_notebook->Connect + ( + wxEVT_NOTEBOOK_PAGE_CHANGED, + wxNotebookEventHandler( + wxGenericMDIClientWindow::OnPageChanged), + NULL, + this + ); + // now that we have a notebook to resize, hook up OnSize() too + Connect(wxEVT_SIZE, wxSizeEventHandler(wxGenericMDIClientWindow::OnSize)); -wxGenericMDIClientWindow::wxGenericMDIClientWindow() -{ + return true; } -wxGenericMDIClientWindow::wxGenericMDIClientWindow( wxGenericMDIParentFrame *parent, long style ) +wxBookCtrlBase *wxGenericMDIClientWindow::GetBookCtrl() const { - CreateClient( parent, style ); + return m_notebook; } -wxGenericMDIClientWindow::~wxGenericMDIClientWindow() +wxGenericMDIChildFrame *wxGenericMDIClientWindow::GetChild(size_t pos) const { - DestroyChildren(); + return static_cast(GetBookCtrl()->GetPage(pos)); } -bool wxGenericMDIClientWindow::CreateClient( wxGenericMDIParentFrame *parent, long style ) +int wxGenericMDIClientWindow::FindChild(wxGenericMDIChildFrame *child) const { - SetWindowStyleFlag(style); - - bool success = wxNotebook::Create(parent, wxID_NOTEBOOK_CLIENT_AREA, wxPoint(), wxSize(100, 100), 0); - if (success) + wxBookCtrlBase * const book = GetBookCtrl(); + const size_t count = book->GetPageCount(); + for ( size_t pos = 0; pos < count; pos++ ) { - /* - wxFont font(10, wxSWISS, wxNORMAL, wxNORMAL); - wxFont selFont(10, wxSWISS, wxNORMAL, wxBOLD); - GetTabView()->SetTabFont(font); - GetTabView()->SetSelectedTabFont(selFont); - GetTabView()->SetTabSize(120, 18); - GetTabView()->SetTabSelectionHeight(20); - */ - return true; + if ( book->GetPage(pos) == child ) + return pos; } - else - return false; -} -int wxGenericMDIClientWindow::SetSelection(size_t nPage) -{ - int oldSelection = wxNotebook::SetSelection(nPage); - -#if !defined(__WXMSW__) // No need to do this for wxMSW as wxNotebook::SetSelection() - // will already cause this to be done! - // Handle the page change. - PageChanged(oldSelection, nPage); -#endif - - return oldSelection; + return wxNOT_FOUND; } -void wxGenericMDIClientWindow::PageChanged(int OldSelection, int newSelection) +void wxGenericMDIClientWindow::PageChanged(int oldSelection, int newSelection) { - // Don't do to much work, only when something realy should change! - if (OldSelection == newSelection) + // Don't do anything if nothing changed + if (oldSelection == newSelection) return; - // Again check if we realy need to do this... + + // Again check if we really need to do this... if (newSelection != -1) { - wxGenericMDIChildFrame* child = (wxGenericMDIChildFrame *)GetPage(newSelection); + wxGenericMDIChildFrame * const child = GetChild(newSelection); - if (child->GetMDIParentFrame()->GetActiveChild() == child) + if ( child->GetGenericMDIParent()->WXIsActiveChild(child) ) return; } // Notify old active child that it has been deactivated - if (OldSelection != -1) + if (oldSelection != -1) { - wxGenericMDIChildFrame* oldChild = (wxGenericMDIChildFrame *)GetPage(OldSelection); + wxGenericMDIChildFrame * const oldChild = GetChild(oldSelection); if (oldChild) { wxActivateEvent event(wxEVT_ACTIVATE, false, oldChild->GetId()); @@ -758,60 +603,41 @@ void wxGenericMDIClientWindow::PageChanged(int OldSelection, int newSelection) // Notify new active child that it has been activated if (newSelection != -1) { - wxGenericMDIChildFrame* activeChild = (wxGenericMDIChildFrame *)GetPage(newSelection); - if (activeChild) + wxGenericMDIChildFrame * const activeChild = GetChild(newSelection); + if ( activeChild ) { wxActivateEvent event(wxEVT_ACTIVATE, true, activeChild->GetId()); event.SetEventObject( activeChild ); activeChild->GetEventHandler()->ProcessEvent(event); - if (activeChild->GetMDIParentFrame()) + wxGenericMDIParentFrame * const + parent = activeChild->GetGenericMDIParent(); + + if ( parent ) { - activeChild->GetMDIParentFrame()->SetActiveChild(activeChild); - activeChild->GetMDIParentFrame()->SetChildMenuBar(activeChild); + // this is a dirty hack as activeChild is not really a + // wxMDIChildFrame at all but we still want to store it in the + // base class m_currentChild field and this will work as long + // as we only use as wxMDIChildFrameBase pointer (which it is) + parent->SetActiveChild( + reinterpret_cast(activeChild)); + parent->WXSetChildMenuBar(activeChild); } } } } -void wxGenericMDIClientWindow::OnPageChanged(wxNotebookEvent& event) +void wxGenericMDIClientWindow::OnPageChanged(wxBookCtrlEvent& event) { PageChanged(event.GetOldSelection(), event.GetSelection()); event.Skip(); } -void wxGenericMDIClientWindow::OnSize(wxSizeEvent& event) +void wxGenericMDIClientWindow::OnSize(wxSizeEvent& WXUNUSED(event)) { - wxNotebook::OnSize(event); - - size_t pos; - for (pos = 0; pos < GetPageCount(); pos++) - { - ((wxGenericMDIChildFrame *)GetPage(pos))->ApplyMDIChildFrameRect(); - } + m_notebook->SetSize(GetClientSize()); } - -/* - * Define normal wxMDI classes based on wxGenericMDI - */ - -#if wxUSE_GENERIC_MDI_AS_NATIVE - -wxMDIChildFrame * wxMDIParentFrame::GetActiveChild() const - { - wxGenericMDIChildFrame *pGFrame = wxGenericMDIParentFrame::GetActiveChild(); - wxMDIChildFrame *pFrame = wxDynamicCast(pGFrame, wxMDIChildFrame); - - wxASSERT_MSG(!(pFrame == NULL && pGFrame != NULL), wxT("Active frame is class not derived from wxMDIChildFrame!")); - - return pFrame; - } - -IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxGenericMDIParentFrame) -IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxGenericMDIChildFrame) -IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxGenericMDIClientWindow) - -#endif +#endif // wxUSE_MDI