From: Julian Smart Date: Tue, 20 Aug 2002 09:27:29 +0000 (+0000) Subject: Added generic MDI files X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/6c70a9b5948d72877e2b96c3ba381e834dea26b1 Added generic MDI files git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@16611 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/generic/mdig.h b/include/wx/generic/mdig.h new file mode 100644 index 0000000000..b39318a659 --- /dev/null +++ b/include/wx/generic/mdig.h @@ -0,0 +1,336 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/generic/mdig.h +// Purpose: Generic MDI (Multiple Document Interface) classes +// Author: Hans Van Leemputten +// Modified by: +// Created: 29/07/2002 +// RCS-ID: $Id$ +// Copyright: (c) Hans Van Leemputten +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_MDIG_H_ +#define _WX_MDIG_H_ + +#ifdef __GNUG__ + #pragma interface "mdig.h" +#endif + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#include "wx/frame.h" +#include "wx/panel.h" +#include "wx/notebook.h" + +WXDLLEXPORT_DATA(extern const wxChar*) wxFrameNameStr; +WXDLLEXPORT_DATA(extern const wxChar*) wxStatusLineNameStr; + + +//----------------------------------------------------------------------------- +// classes +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxGenericMDIParentFrame; +class WXDLLEXPORT wxGenericMDIClientWindow; +class WXDLLEXPORT wxGenericMDIChildFrame; + +//----------------------------------------------------------------------------- +// wxGenericMDIParentFrame +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxGenericMDIParentFrame: public wxFrame +{ +public: + wxGenericMDIParentFrame(); + wxGenericMDIParentFrame(wxWindow *parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE | wxVSCROLL | wxHSCROLL, + const wxString& name = wxFrameNameStr); + + ~wxGenericMDIParentFrame(); + bool Create( wxWindow *parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE | wxVSCROLL | wxHSCROLL, + const wxString& name = wxFrameNameStr ); + +#if wxUSE_MENUS + wxMenu* GetWindowMenu() const { return m_pWindowMenu; }; + void SetWindowMenu(wxMenu* pMenu); + + virtual void SetMenuBar(wxMenuBar *pMenuBar); +#endif // wxUSE_MENUS + + void SetChildMenuBar(wxGenericMDIChildFrame *pChild); + + virtual bool ProcessEvent(wxEvent& event); + + wxGenericMDIChildFrame *GetActiveChild() const; + inline void SetActiveChild(wxGenericMDIChildFrame* pChildFrame); + + wxGenericMDIClientWindow *GetClientWindow() const; + virtual wxGenericMDIClientWindow *OnCreateClient(); + + virtual void Cascade() { /* Has no effect */ } + virtual void Tile() { /* Has no effect */ } + virtual void ArrangeIcons() { /* Has no effect */ } + virtual void ActivateNext(); + virtual void ActivatePrevious(); + +protected: + wxGenericMDIClientWindow *m_pClientWindow; + wxGenericMDIChildFrame *m_pActiveChild; +#if wxUSE_MENUS + wxMenu *m_pWindowMenu; + wxMenuBar *m_pMyMenuBar; +#endif // wxUSE_MENUS + +protected: + void Init(); + +#if wxUSE_MENUS + void RemoveWindowMenu(wxMenuBar *pMenuBar); + void AddWindowMenu(wxMenuBar *pMenuBar); + + void DoHandleMenu(wxCommandEvent &event); +#endif // wxUSE_MENUS + + virtual void DoGetClientSize(int *width, int *height) const; + +private: + DECLARE_EVENT_TABLE() + DECLARE_DYNAMIC_CLASS(wxGenericMDIParentFrame) +}; + +//----------------------------------------------------------------------------- +// wxGenericMDIChildFrame +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxGenericMDIChildFrame: public wxPanel +{ +public: + wxGenericMDIChildFrame(); + wxGenericMDIChildFrame( wxGenericMDIParentFrame *parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE, + const wxString& name = wxFrameNameStr ); + + virtual ~wxGenericMDIChildFrame(); + bool Create( wxGenericMDIParentFrame *parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE, + const wxString& name = wxFrameNameStr ); + +#if wxUSE_MENUS + virtual void SetMenuBar( wxMenuBar *menu_bar ); + virtual wxMenuBar *GetMenuBar() const; +#endif // wxUSE_MENUS + + virtual void SetTitle(const wxString& title); + virtual wxString GetTitle(); + + virtual void Activate(); + +#if wxUSE_STATUSBAR + // no status bars + virtual wxStatusBar* CreateStatusBar( int WXUNUSED(number) = 1, + long WXUNUSED(style) = 1, + wxWindowID WXUNUSED(id) = 1, + const wxString& WXUNUSED(name) = wxEmptyString) + { return (wxStatusBar*)NULL; } + + virtual wxStatusBar *GetStatusBar() const { return (wxStatusBar*)NULL; } + virtual void SetStatusText( const wxString &WXUNUSED(text), int WXUNUSED(number)=0 ) {} + virtual void SetStatusWidths( int WXUNUSED(n), const int WXUNUSED(widths_field)[] ) {} +#endif + + // no size hints + virtual void SetSizeHints( int WXUNUSED(minW), + int WXUNUSED(minH), + int WXUNUSED(maxW) = -1, + int WXUNUSED(maxH) = -1, + int WXUNUSED(incW) = -1, + int WXUNUSED(incH) = -1) {} + +#if wxUSE_TOOLBAR + // no toolbar bars + virtual wxToolBar* CreateToolBar( long WXUNUSED(style), + wxWindowID WXUNUSED(id), + const wxString& WXUNUSED(name) ) + { return (wxToolBar*)NULL; } + virtual wxToolBar *GetToolBar() const { return (wxToolBar*)NULL; } +#endif + + // no icon + void SetIcon( const wxIcon &icon ) { /*m_icons = wxIconBundle( icon );*/} + void SetIcons( const wxIconBundle &icons ) { /*m_icons = icons;*/ } + + // no maximize etc + virtual void Maximize( bool WXUNUSED(maximize) = TRUE) { /* Has no effect */ } + virtual void Restore() { /* Has no effect */ } + virtual void Iconize(bool WXUNUSED(iconize) = TRUE) { /* Has no effect */ } + virtual bool IsMaximized() const { return TRUE; } + virtual bool IsIconized() const { return FALSE; } + virtual bool ShowFullScreen(bool WXUNUSED(show), long WXUNUSED(style)) { return FALSE; } + virtual bool IsFullScreen() const { return FALSE; } + + virtual bool IsTopLevel() const { return FALSE; } + + void OnMenuHighlight(wxMenuEvent& event); + void OnActivate(wxActivateEvent& event); + + // The next 2 are copied from top level... + void OnCloseWindow(wxCloseEvent& event); + void OnSize(wxSizeEvent& event); + + void SetMDIParentFrame(wxGenericMDIParentFrame* parentFrame); + wxGenericMDIParentFrame* GetMDIParentFrame() const; + +protected: + wxGenericMDIParentFrame *m_pMDIParentFrame; + wxRect m_MDIRect; + wxString m_Title; + +#if wxUSE_MENUS + wxMenuBar *m_pMenuBar; +#endif // wxUSE_MENUS + +protected: + void Init(); + + virtual void DoMoveWindow(int x, int y, int width, int height); + + // This function needs to be called when a size change is confirmed, + // we needed this function to prevent any body from the outside + // changing the panel... it messes the UI layout when we would allow it. + void ApplyMDIChildFrameRect(); + +private: + DECLARE_DYNAMIC_CLASS(wxGenericMDIChildFrame) + DECLARE_EVENT_TABLE() + + friend class wxGenericMDIClientWindow; +}; + +//----------------------------------------------------------------------------- +// wxGenericMDIClientWindow +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxGenericMDIClientWindow: public wxNotebook +{ +public: + wxGenericMDIClientWindow(); + wxGenericMDIClientWindow( wxGenericMDIParentFrame *parent, long style = 0 ); + ~wxGenericMDIClientWindow(); + virtual bool CreateClient( wxGenericMDIParentFrame *parent, long style = wxVSCROLL | wxHSCROLL ); + + virtual int SetSelection(int nPage); + +protected: + void PageChanged(int OldSelection, int newSelection); + + void OnPageChanged(wxNotebookEvent& event); + void OnSize(wxSizeEvent& event); + +private: + DECLARE_DYNAMIC_CLASS(wxGenericMDIClientWindow) + DECLARE_EVENT_TABLE() +}; + + +/* + * Define normal wxMDI classes based on wxGenericMDI + */ + +#ifndef wxUSE_GENERIC_MDI_AS_NATIVE +#if defined(__WXUNIVERSAL__) +#define wxUSE_GENERIC_MDI_AS_NATIVE 1 +#else +#define wxUSE_GENERIC_MDI_AS_NATIVE 0 +#endif +#endif // wxUSE_GENERIC_MDI_AS_NATIVE + +#if wxUSE_GENERIC_MDI_AS_NATIVE + +//----------------------------------------------------------------------------- +// wxMDIParentFrame +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxMDIParentFrame: public wxGenericMDIParentFrame +{ +public: + wxMDIParentFrame() {} + wxMDIParentFrame(wxWindow *parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE | wxVSCROLL | wxHSCROLL, + const wxString& name = wxFrameNameStr) + :wxGenericMDIParentFrame(parent, id, title, pos, size, style, name) + { + } + +private: + DECLARE_DYNAMIC_CLASS(wxMDIParentFrame) +}; + +//----------------------------------------------------------------------------- +// wxMDIChildFrame +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxMDIChildFrame: public wxGenericMDIChildFrame +{ +public: + wxMDIChildFrame() {} + + wxMDIChildFrame( wxGenericMDIParentFrame *parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE, + const wxString& name = wxFrameNameStr ) + :wxGenericMDIChildFrame(parent, id, title, pos, size, style, name) + { + } + +private: + DECLARE_DYNAMIC_CLASS(wxMDIChildFrame) +}; + +//----------------------------------------------------------------------------- +// wxMDIClientWindow +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxMDIClientWindow: public wxGenericMDIClientWindow +{ +public: + wxMDIClientWindow() {} + + wxMDIClientWindow( wxGenericMDIParentFrame *parent, long style = 0 ) + :wxGenericMDIClientWindow(parent, style) + { + } + +private: + DECLARE_DYNAMIC_CLASS(wxMDIClientWindow) +}; + +#endif + +#endif + // _WX_MDIG_H_ diff --git a/src/generic/mdig.cpp b/src/generic/mdig.cpp new file mode 100644 index 0000000000..69445c6b27 --- /dev/null +++ b/src/generic/mdig.cpp @@ -0,0 +1,801 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: src/generic/mdig.cpp +// Purpose: Generic MDI (Multiple Document Interface) classes +// Author: Hans Van Leemputten +// Modified by: +// Created: 29/07/2002 +// RCS-ID: $Id$ +// Copyright: (c) Hans Van Leemputten +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +// =========================================================================== +// declarations +// =========================================================================== + +// --------------------------------------------------------------------------- +// headers +// --------------------------------------------------------------------------- + +#ifdef __GNUG__ + #pragma implementation "mdig.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/panel.h" + #include "wx/menu.h" +#endif //WX_PRECOMP + +#include "wx/generic/mdig.h" + +enum MDI_MENU_ID +{ + wxWINDOWCLOSE = 4001, + wxWINDOWCLOSEALL, + wxWINDOWNEXT, + wxWINDOWPREV +}; + +//----------------------------------------------------------------------------- +// wxGenericMDIParentFrame +//----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIParentFrame, wxFrame) + +BEGIN_EVENT_TABLE(wxGenericMDIParentFrame, wxFrame) + EVT_MENU (-1, wxGenericMDIParentFrame::DoHandleMenu) +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) +{ + Init(); + + (void)Create(parent, id, title, pos, size, style, name); +} + +wxGenericMDIParentFrame::~wxGenericMDIParentFrame() +{ + // Make sure the client window is destructed before the menu bars are! + wxDELETE(m_pClientWindow); + +#if wxUSE_MENUS + if (m_pMyMenuBar) + { + delete m_pMyMenuBar; + m_pMyMenuBar = (wxMenuBar *) NULL; + } + + RemoveWindowMenu(GetMenuBar()); + + if (m_pWindowMenu) + { + delete m_pWindowMenu; + m_pWindowMenu = (wxMenu*) NULL; + } +#endif // wxUSE_MENUS +} + +bool wxGenericMDIParentFrame::Create(wxWindow *parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos, + const wxSize& size, + 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) ) + { +#if wxUSE_MENUS + m_pWindowMenu = new wxMenu; + + m_pWindowMenu->Append(wxWINDOWCLOSE, _T("Cl&ose")); + m_pWindowMenu->Append(wxWINDOWCLOSEALL, _T("Close Al&l")); + m_pWindowMenu->AppendSeparator(); + m_pWindowMenu->Append(wxWINDOWNEXT, _T("&Next")); + m_pWindowMenu->Append(wxWINDOWPREV, _T("&Previouse")); +#endif // wxUSE_MENUS + } + + wxFrame::Create( parent, id, title, pos, size, style, name ); + + OnCreateClient(); + + return TRUE; +} + +#if wxUSE_MENUS +void wxGenericMDIParentFrame::SetWindowMenu(wxMenu* pMenu) +{ + // Replace the window menu from the currently loaded menu bar. + wxMenuBar *pMenuBar = GetMenuBar(); + + if (m_pWindowMenu) + { + RemoveWindowMenu(pMenuBar); + + wxDELETE(m_pWindowMenu); + } + + if (pMenu) + { + m_pWindowMenu = pMenu; + + AddWindowMenu(pMenuBar); + } +} + +void wxGenericMDIParentFrame::SetMenuBar(wxMenuBar *pMenuBar) +{ + // Remove the Window menu from the old menu bar + RemoveWindowMenu(GetMenuBar()); + // Add the Window menu to the new menu bar. + AddWindowMenu(pMenuBar); + + wxFrame::SetMenuBar(pMenuBar); +} +#endif // wxUSE_MENUS + +void wxGenericMDIParentFrame::SetChildMenuBar(wxGenericMDIChildFrame *pChild) +{ +#if wxUSE_MENUS + if (pChild == (wxGenericMDIChildFrame *) 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; + } + else + { + if (pChild->GetMenuBar() == (wxMenuBar*) NULL) + return; + + // Do we need to save the current bar? + if (m_pMyMenuBar == NULL) + m_pMyMenuBar = GetMenuBar(); + + SetMenuBar(pChild->GetMenuBar()); + } +#endif // wxUSE_MENUS +} + +bool wxGenericMDIParentFrame::ProcessEvent(wxEvent& event) +{ + /* + * 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; +} + +wxGenericMDIChildFrame *wxGenericMDIParentFrame::GetActiveChild() const +{ + return m_pActiveChild; +} + +void wxGenericMDIParentFrame::SetActiveChild(wxGenericMDIChildFrame* pChildFrame) +{ + m_pActiveChild = pChildFrame; +} + +wxGenericMDIClientWindow *wxGenericMDIParentFrame::GetClientWindow() const +{ + return m_pClientWindow; +} + +wxGenericMDIClientWindow *wxGenericMDIParentFrame::OnCreateClient() +{ +#if wxUSE_GENERIC_MDI_AS_NATIVE + m_pClientWindow = new wxMDIClientWindow( this ); +#else + m_pClientWindow = new wxGenericMDIClientWindow( this ); +#endif + return m_pClientWindow; +} + +void wxGenericMDIParentFrame::ActivateNext() +{ + if (m_pClientWindow && m_pClientWindow->GetSelection() != -1) + { + int active = m_pClientWindow->GetSelection() + 1; + if (active >= m_pClientWindow->GetPageCount()) + active = 0; + + m_pClientWindow->SetSelection(active); + } +} + +void wxGenericMDIParentFrame::ActivatePrevious() +{ + if (m_pClientWindow && m_pClientWindow->GetSelection() != -1) + { + int active = m_pClientWindow->GetSelection() - 1; + if (active < 0) + active = m_pClientWindow->GetPageCount() - 1; + + m_pClientWindow->SetSelection(active); + } +} + +void wxGenericMDIParentFrame::Init() +{ + m_pClientWindow = (wxGenericMDIClientWindow *) NULL; + m_pActiveChild = (wxGenericMDIChildFrame *) NULL; +#if wxUSE_MENUS + m_pWindowMenu = (wxMenu *) NULL; + m_pMyMenuBar = (wxMenuBar*) NULL; +#endif // wxUSE_MENUS +} + +#if wxUSE_MENUS +void wxGenericMDIParentFrame::RemoveWindowMenu(wxMenuBar *pMenuBar) +{ + if (pMenuBar && m_pWindowMenu) + { + // Remove old window menu + int pos = pMenuBar->FindMenu(_T("&Window")); + if (pos != wxNOT_FOUND) + { + wxASSERT(m_pWindowMenu == pMenuBar->GetMenu(pos)); // DBG:: We're going to delete the wrong menu!!! + pMenuBar->Remove(pos); + } + } +} + +void wxGenericMDIParentFrame::AddWindowMenu(wxMenuBar *pMenuBar) +{ + if (pMenuBar && m_pWindowMenu) + { + int pos = pMenuBar->FindMenu(_T("Help")); + if (pos == wxNOT_FOUND) + { + pMenuBar->Append(m_pWindowMenu, _T("&Window")); + } + else + { + pMenuBar->Insert(pos, m_pWindowMenu, _T("&Window")); + } + } +} + +void wxGenericMDIParentFrame::DoHandleMenu(wxCommandEvent &event) +{ + 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(); + } +} +#endif // wxUSE_MENUS + +void wxGenericMDIParentFrame::DoGetClientSize(int *width, int *height) const +{ + wxFrame::DoGetClientSize( width, height ); +} + + +//----------------------------------------------------------------------------- +// wxGenericMDIChildFrame +//----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIChildFrame, wxPanel) + +BEGIN_EVENT_TABLE(wxGenericMDIChildFrame, wxPanel) + EVT_MENU_HIGHLIGHT_ALL(wxGenericMDIChildFrame::OnMenuHighlight) + EVT_ACTIVATE(wxGenericMDIChildFrame::OnActivate) + + EVT_CLOSE(wxGenericMDIChildFrame::OnCloseWindow) + EVT_SIZE(wxGenericMDIChildFrame::OnSize) +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 ) +{ + Init(); + + Create( parent, id, title, wxDefaultPosition, size, style, name ); +} + +#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; + } + + wxGenericMDIClientWindow *pClientWindow = pParentFrame->GetClientWindow(); + + // Remove page if still there + int 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 (pClientWindow->GetPageCount() - 1 >= 0) + pClientWindow->SetSelection(pClientWindow->GetPageCount() - 1); + } + } + } + +#if wxUSE_MENUS + wxDELETE(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 ) +{ + wxGenericMDIClientWindow* pClientWindow = parent->GetClientWindow(); + + wxASSERT_MSG((pClientWindow != (wxWindow*) NULL), "Missing MDI client window."); + + wxPanel::Create(pClientWindow, id, wxDefaultPosition, size, style, name); + + SetMDIParentFrame(parent); + + // This is the currently active child + parent->SetActiveChild(this); + + m_Title = title; + + pClientWindow->AddPage(this, title, TRUE); + ApplyMDIChildFrameRect(); // Ok confirme the size change! + pClientWindow->Refresh(); + + return TRUE; +} + +#if wxUSE_MENUS +void wxGenericMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar ) +{ + wxMenuBar *pOldMenuBar = m_pMenuBar; + m_pMenuBar = menu_bar; + + if (m_pMenuBar) + { + wxGenericMDIParentFrame *pParentFrame = GetMDIParentFrame(); + + if (pParentFrame != NULL) + { + m_pMenuBar->SetParent(pParentFrame); + + if (pParentFrame->GetActiveChild() == this) + { + // Replace current menu bars + if (pOldMenuBar) + pParentFrame->SetChildMenuBar((wxGenericMDIChildFrame*) NULL); + pParentFrame->SetChildMenuBar((wxGenericMDIChildFrame*) this); + } + } + } +} + +wxMenuBar *wxGenericMDIChildFrame::GetMenuBar() const +{ + return m_pMenuBar; +} +#endif // wxUSE_MENUS + +void wxGenericMDIChildFrame::SetTitle(const wxString& title) +{ + m_Title = title; + + wxGenericMDIParentFrame *pParentFrame = GetMDIParentFrame(); + + if (pParentFrame != NULL) + { + wxGenericMDIClientWindow * pClientWindow = pParentFrame->GetClientWindow(); + + if (pClientWindow != NULL) + { + int pos; + for (pos = 0; pos < pClientWindow->GetPageCount(); pos++) + { + if (pClientWindow->GetPage(pos) == this) + { + pClientWindow->SetPageText(pos, m_Title); + break; + } + } + } + } +} + +wxString wxGenericMDIChildFrame::GetTitle() +{ + return m_Title; +} + +void wxGenericMDIChildFrame::Activate() +{ + wxGenericMDIParentFrame *pParentFrame = GetMDIParentFrame(); + + if (pParentFrame != NULL) + { + wxGenericMDIClientWindow * pClientWindow = pParentFrame->GetClientWindow(); + + if (pClientWindow != NULL) + { + int pos; + for (pos = 0; pos < pClientWindow->GetPageCount(); pos++) + { + if (pClientWindow->GetPage(pos) == this) + { + pClientWindow->SetSelection(pos); + break; + } + } + } + } +} + +void wxGenericMDIChildFrame::OnMenuHighlight(wxMenuEvent& event) +{ +#if wxUSE_STATUSBAR + if ( m_pMDIParentFrame) + { + // we don't have any help text for this item, + // but may be the MDI frame does? + m_pMDIParentFrame->OnMenuHighlight(event); + } +#endif // wxUSE_STATUSBAR +} + +void wxGenericMDIChildFrame::OnActivate(wxActivateEvent& 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::Node *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 +} + +void wxGenericMDIChildFrame::DoMoveWindow(int x, int y, int width, int height) +{ + m_MDIRect = wxRect(x, y, width, height); +} + +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, wxNotebook) + +BEGIN_EVENT_TABLE(wxGenericMDIClientWindow, wxNotebook) + EVT_NOTEBOOK_PAGE_CHANGED(wxID_NOTEBOOK_CLIENT_AREA, wxGenericMDIClientWindow::OnPageChanged) + EVT_SIZE(wxGenericMDIClientWindow::OnSize) +END_EVENT_TABLE() + + +wxGenericMDIClientWindow::wxGenericMDIClientWindow() +{ +} + +wxGenericMDIClientWindow::wxGenericMDIClientWindow( wxGenericMDIParentFrame *parent, long style ) +{ + CreateClient( parent, style ); +} + +wxGenericMDIClientWindow::~wxGenericMDIClientWindow() +{ + DestroyChildren(); +} + +bool wxGenericMDIClientWindow::CreateClient( wxGenericMDIParentFrame *parent, long style ) +{ + SetWindowStyleFlag(style); + + bool success = wxNotebook::Create(parent, wxID_NOTEBOOK_CLIENT_AREA, wxPoint(0, 0), wxSize(100, 100), 0); + if (success) + { + /* + 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; + } + else + return FALSE; +} + +int wxGenericMDIClientWindow::SetSelection(int 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; +} + +void wxGenericMDIClientWindow::PageChanged(int OldSelection, int newSelection) +{ + // Don't do to much work, only when something realy should change! + if (OldSelection == newSelection) + return; + // Again check if we realy need to do this... + if (newSelection != -1) + { + wxGenericMDIChildFrame* child = (wxGenericMDIChildFrame *)GetPage(newSelection); + + if (child->GetMDIParentFrame()->GetActiveChild() == child) + return; + } + + // Notify old active child that it has been deactivated + if (OldSelection != -1) + { + wxGenericMDIChildFrame* oldChild = (wxGenericMDIChildFrame *)GetPage(OldSelection); + if (oldChild) + { + wxActivateEvent event(wxEVT_ACTIVATE, FALSE, oldChild->GetId()); + event.SetEventObject( oldChild ); + oldChild->GetEventHandler()->ProcessEvent(event); + } + } + + // Notify new active child that it has been activated + if (newSelection != -1) + { + wxGenericMDIChildFrame* activeChild = (wxGenericMDIChildFrame *)GetPage(newSelection); + if (activeChild) + { + wxActivateEvent event(wxEVT_ACTIVATE, TRUE, activeChild->GetId()); + event.SetEventObject( activeChild ); + activeChild->GetEventHandler()->ProcessEvent(event); + + if (activeChild->GetMDIParentFrame()) + { + activeChild->GetMDIParentFrame()->SetActiveChild(activeChild); + activeChild->GetMDIParentFrame()->SetChildMenuBar(activeChild); + } + } + } +} + +void wxGenericMDIClientWindow::OnPageChanged(wxNotebookEvent& event) +{ + PageChanged(event.GetOldSelection(), event.GetSelection()); + + event.Skip(); +} + +void wxGenericMDIClientWindow::OnSize(wxSizeEvent& event) +{ + wxNotebook::OnSize(event); + + int pos; + for (pos = 0; pos < GetPageCount(); pos++) + { + ((wxGenericMDIChildFrame *)GetPage(pos))->ApplyMDIChildFrameRect(); + } +} + + +/* + * Define normal wxMDI classes based on wxGenericMDI + */ + +#if wxUSE_GENERIC_MDI_AS_NATIVE + +IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxGenericMDIParentFrame) +IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxGenericMDIChildFrame) +IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxGenericMDIClientWindow) + +#endif +