// 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
/////////////////////////////////////////////////////////////////////////////
// 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"
#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
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;
+ m_pMyMenuBar = NULL;
}
RemoveWindowMenu(GetMenuBar());
-
- if (m_pWindowMenu)
- {
- delete m_pWindowMenu;
- m_pWindowMenu = (wxMenu*) NULL;
- }
#endif // wxUSE_MENUS
}
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;
- return true;
+ wxGenericMDIClientWindow * const client = OnCreateGenericClient();
+ if ( !client->CreateGenericClient(this) )
+ return false;
+
+ 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
// 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);
}
}
#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?
#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<wxGenericMDIClientWindow *>(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<wxMDIChildFrameBase *>(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);
}
}
void wxGenericMDIParentFrame::AddWindowMenu(wxMenuBar *pMenuBar)
{
- if (pMenuBar && m_pWindowMenu)
+ if (pMenuBar && m_windowMenu)
{
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;
- m_pActiveChild = NULL;
-#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_COMMAND_MENU_SELECTED ||
+ 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();
-
- if (pParentFrame != NULL)
- {
- bool bActive = false;
- if (pParentFrame->GetActiveChild() == this)
- {
- pParentFrame->SetActiveChild((wxGenericMDIChildFrame*) NULL);
- pParentFrame->SetChildMenuBar((wxGenericMDIChildFrame*) NULL);
- bActive = true;
- }
+ wxGenericMDIParentFrame * const parent = GetGenericMDIParent();
- 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;
}
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);
}
}
}
void wxGenericMDIChildFrame::SetTitle(const wxString& title)
{
- m_Title = title;
-
- wxGenericMDIParentFrame *pParentFrame = GetMDIParentFrame();
-
- 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;
- }
- }
- }
- }
-}
+ m_title = title;
-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);
- }
-#else
- wxUnusedVar(event);
-#endif // wxUSE_STATUSBAR
-}
-
-void wxGenericMDIChildFrame::OnActivate(wxActivateEvent& WXUNUSED(event))
-{
- // Do mothing.
-}
-
-/*** Copied from top level..! ***/
-// default resizing behaviour - if only ONE subwindow, resize to fill the
-// whole client area
-void wxGenericMDIChildFrame::OnSize(wxSizeEvent& WXUNUSED(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);
- }
+ parent->OnMenuHighlight(event);
}
}
-/*** 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()
+void wxGenericMDIChildFrame::OnClose(wxCloseEvent& WXUNUSED(event))
{
- m_pMDIParentFrame = (wxGenericMDIParentFrame *) NULL;
-#if wxUSE_MENUS
- m_pMenuBar = (wxMenuBar *) NULL;
-#endif // wxUSE_MENUS
+ // we're not a TLW so don't delay the destruction of this window
+ delete this;
}
-void wxGenericMDIChildFrame::DoMoveWindow(int x, int y, int width, int height)
+bool wxGenericMDIChildFrame::TryAfter(wxEvent& event)
{
- m_MDIRect = wxRect(x, y, width, height);
-}
+ // 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::ApplyMDIChildFrameRect()
-{
- wxPanel::DoMoveWindow(m_MDIRect.x, m_MDIRect.y, m_MDIRect.width, m_MDIRect.height);
+ return wxTDIChildFrame::TryAfter(event);
}
-//-----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// 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_COMMAND_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<wxGenericMDIChildFrame *>(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(0,0), 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());
// 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<wxMDIChildFrame *>(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