X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ef0e92205a01c7d0ca6f381cc690cb5d4fa595c9..4f2d6692c7119cbe213f04cd80d8e697bf3533ae:/include/wx/mdi.h diff --git a/include/wx/mdi.h b/include/wx/mdi.h index 0c12f3d871..837c132822 100644 --- a/include/wx/mdi.h +++ b/include/wx/mdi.h @@ -1,11 +1,10 @@ ///////////////////////////////////////////////////////////////////////////// // Name: wx/mdi.h // Purpose: wxMDI base header -// Author: Julian Smart -// Modified by: -// Created: -// Copyright: (c) Julian Smart -// RCS-ID: $Id$ +// Author: Julian Smart (original) +// Vadim Zeitlin (base MDI classes refactoring) +// Copyright: (c) 1998 Julian Smart +// (c) 2008 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -16,12 +15,348 @@ #if wxUSE_MDI -#if defined(__WXUNIVERSAL__) +#include "wx/frame.h" +#include "wx/menu.h" + +// forward declarations +class WXDLLIMPEXP_FWD_CORE wxMDIParentFrame; +class WXDLLIMPEXP_FWD_CORE wxMDIChildFrame; +class WXDLLIMPEXP_FWD_CORE wxMDIClientWindowBase; +class WXDLLIMPEXP_FWD_CORE wxMDIClientWindow; + +// ---------------------------------------------------------------------------- +// wxMDIParentFrameBase: base class for parent frame for MDI children +// ---------------------------------------------------------------------------- + +class WXDLLIMPEXP_CORE wxMDIParentFrameBase : public wxFrame +{ +public: + wxMDIParentFrameBase() + { + m_clientWindow = NULL; + m_currentChild = NULL; +#if wxUSE_MENUS + m_windowMenu = NULL; +#endif // wxUSE_MENUS + } + + /* + Derived classes should provide ctor and Create() with the following + declaration: + + bool Create(wxWindow *parent, + wxWindowID winid, + 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 + virtual ~wxMDIParentFrameBase() + { + delete m_windowMenu; + } +#endif // wxUSE_MENUS + + // accessors + // --------- + + // Get or change the active MDI child window + virtual wxMDIChildFrame *GetActiveChild() const + { return m_currentChild; } + virtual void SetActiveChild(wxMDIChildFrame *child) + { m_currentChild = child; } + + + // Get the client window + wxMDIClientWindowBase *GetClientWindow() const { return m_clientWindow; } + + + // MDI windows menu functions + // -------------------------- + +#if wxUSE_MENUS + // return the pointer to the current window menu or NULL if we don't have + // because of wxFRAME_NO_WINDOW_MENU style + wxMenu* GetWindowMenu() const { return m_windowMenu; } + + // use the given menu instead of the default window menu + // + // menu can be NULL to disable the window menu completely + virtual void SetWindowMenu(wxMenu *menu) + { + if ( menu != m_windowMenu ) + { + delete m_windowMenu; + m_windowMenu = menu; + } + } +#endif // wxUSE_MENUS + + + // standard MDI window management functions + // ---------------------------------------- + + virtual void Cascade() { } + virtual void Tile(wxOrientation WXUNUSED(orient) = wxHORIZONTAL) { } + virtual void ArrangeIcons() { } + virtual void ActivateNext() = 0; + virtual void ActivatePrevious() = 0; + + /* + Derived classes must provide the following function: + + static bool IsTDI(); + */ + + // Create the client window class (don't Create() the window here, just + // return a new object of a wxMDIClientWindow-derived class) + // + // Notice that if you override this method you should use the default + // constructor and Create() and not the constructor creating the window + // when creating the frame or your overridden version is not going to be + // called (as the call to a virtual function from ctor will be dispatched + // to this class version) + virtual wxMDIClientWindow *OnCreateClient(); + +protected: + // Override to pass menu/toolbar events to the active child first. + virtual bool TryBefore(wxEvent& event); + + + // This is wxMDIClientWindow for all the native implementations but not for + // the generic MDI version which has its own wxGenericMDIClientWindow and + // so we store it as just a base class pointer because we don't need its + // exact type anyhow + wxMDIClientWindowBase *m_clientWindow; + wxMDIChildFrame *m_currentChild; + +#if wxUSE_MENUS + // the current window menu or NULL if we are not using it + wxMenu *m_windowMenu; +#endif // wxUSE_MENUS +}; + +// ---------------------------------------------------------------------------- +// wxMDIChildFrameBase: child frame managed by wxMDIParentFrame +// ---------------------------------------------------------------------------- + +class WXDLLIMPEXP_CORE wxMDIChildFrameBase : public wxFrame +{ +public: + wxMDIChildFrameBase() { m_mdiParent = NULL; } + + /* + Derived classes should provide Create() with the following signature: + + bool Create(wxMDIParentFrame *parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE, + const wxString& name = wxFrameNameStr); + + And setting m_mdiParent to parent parameter. + */ + + // MDI children specific methods + virtual void Activate() = 0; + + // Return the MDI parent frame: notice that it may not be the same as + // GetParent() (our parent may be the client window or even its subwindow + // in some implementations) + wxMDIParentFrame *GetMDIParent() const { return m_mdiParent; } + + // Synonym for GetMDIParent(), was used in some other ports + wxMDIParentFrame *GetMDIParentFrame() const { return GetMDIParent(); } + + + // in most ports MDI children frames are not really top-level, the only + // exception are the Mac ports in which MDI children are just normal top + // level windows too + virtual bool IsTopLevel() const { return false; } + + // In all ports keyboard navigation must stop at MDI child frame level and + // can't cross its boundary. Indicate this by overriding this function to + // return true. + virtual bool IsTopNavigationDomain() const { return true; } + + // Raising any frame is supposed to show it but wxFrame Raise() + // implementation doesn't work for MDI child frames in most forms so + // forward this to Activate() which serves the same purpose by default. + virtual void Raise() { Activate(); } + +protected: + wxMDIParentFrame *m_mdiParent; +}; + +// ---------------------------------------------------------------------------- +// wxTDIChildFrame: child frame used by TDI implementations +// ---------------------------------------------------------------------------- + +class WXDLLIMPEXP_CORE wxTDIChildFrame : public wxMDIChildFrameBase +{ +public: + // override wxFrame methods for this non top-level window + +#if wxUSE_STATUSBAR + // no status bars + // + // TODO: MDI children should have their own status bars, why not? + virtual wxStatusBar* CreateStatusBar(int WXUNUSED(number) = 1, + long WXUNUSED(style) = 1, + wxWindowID WXUNUSED(id) = 1, + const wxString& WXUNUSED(name) + = wxEmptyString) + { return NULL; } + + virtual wxStatusBar *GetStatusBar() const + { return NULL; } + virtual void SetStatusText(const wxString &WXUNUSED(text), + int WXUNUSED(number)=0) + { } + virtual void SetStatusWidths(int WXUNUSED(n), + const int WXUNUSED(widths)[]) + { } +#endif // wxUSE_STATUSBAR + +#if wxUSE_TOOLBAR + // no toolbar + // + // TODO: again, it should be possible to have tool bars + virtual wxToolBar *CreateToolBar(long WXUNUSED(style), + wxWindowID WXUNUSED(id), + const wxString& WXUNUSED(name)) + { return NULL; } + virtual wxToolBar *GetToolBar() const { return NULL; } +#endif // wxUSE_TOOLBAR + + // no icon + virtual void SetIcons(const wxIconBundle& WXUNUSED(icons)) { } + + // title is used as the tab label + virtual wxString GetTitle() const { return m_title; } + virtual void SetTitle(const wxString& title) = 0; + + // no maximize etc + virtual void Maximize(bool WXUNUSED(maximize) = true) { } + virtual bool IsMaximized() const { return true; } + virtual bool IsAlwaysMaximized() const { return true; } + virtual void Iconize(bool WXUNUSED(iconize) = true) { } + virtual bool IsIconized() const { return false; } + virtual void Restore() { } + + virtual bool ShowFullScreen(bool WXUNUSED(show), + long WXUNUSED(style)) { return false; } + virtual bool IsFullScreen() const { return false; } + + + // we need to override these functions to ensure that a child window is + // created even though we derive from wxFrame -- basically we make it + // behave as just a wxWindow by short-circuiting wxTLW changes to the base + // class behaviour + + virtual void AddChild(wxWindowBase *child) { wxWindow::AddChild(child); } + + virtual bool Destroy() { return wxWindow::Destroy(); } + + // extra platform-specific hacks +#ifdef __WXMSW__ + virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle = NULL) const + { + return wxWindow::MSWGetStyle(flags, exstyle); + } + + virtual WXHWND MSWGetParent() const + { + return wxWindow::MSWGetParent(); + } + + WXLRESULT MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) + { + return wxWindow::MSWWindowProc(message, wParam, lParam); + } +#endif // __WXMSW__ + +protected: + virtual void DoGetSize(int *width, int *height) const + { + wxWindow::DoGetSize(width, height); + } + + virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags) + { + wxWindow::DoSetSize(x, y, width, height, sizeFlags); + } + + virtual void DoGetClientSize(int *width, int *height) const + { + wxWindow::DoGetClientSize(width, height); + } + + virtual void DoSetClientSize(int width, int height) + { + wxWindow::DoSetClientSize(width, height); + } + + // no size hints + virtual void DoSetSizeHints(int WXUNUSED(minW), int WXUNUSED(minH), + int WXUNUSED(maxW), int WXUNUSED(maxH), + int WXUNUSED(incW), int WXUNUSED(incH)) { } + + wxString m_title; +}; + +// ---------------------------------------------------------------------------- +// wxMDIClientWindowBase: child of parent frame, parent of children frames +// ---------------------------------------------------------------------------- + +class WXDLLIMPEXP_CORE wxMDIClientWindowBase : public wxWindow +{ +public: + /* + The derived class must provide the default ctor only (CreateClient() + will be called later). + */ + + // Can be overridden in the derived classes but the base class version must + // be usually called first to really create the client window. + virtual bool CreateClient(wxMDIParentFrame *parent, + long style = wxVSCROLL | wxHSCROLL) = 0; +}; + +// ---------------------------------------------------------------------------- +// Include the port-specific implementation of the base classes defined above +// ---------------------------------------------------------------------------- + +// wxUSE_GENERIC_MDI_AS_NATIVE may be predefined to force the generic MDI +// implementation use even on the platforms which usually don't use it +// +// notice that generic MDI can still be used without this, but you would need +// to explicitly use wxGenericMDIXXX classes in your code (and currently also +// add src/generic/mdig.cpp to your build as it's not compiled in if generic +// MDI is not used by default -- but this may change later...) +#ifndef wxUSE_GENERIC_MDI_AS_NATIVE + // wxUniv always uses the generic MDI implementation and so do the ports + // without native version (although wxCocoa seems to have one -- but it's + // probably not functional?) + #if defined(__WXCOCOA__) || \ + defined(__WXMOTIF__) || \ + defined(__WXPM__) || \ + 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 #include "wx/generic/mdig.h" #elif defined(__WXMSW__) #include "wx/msw/mdi.h" -#elif defined(__WXMOTIF__) - #include "wx/motif/mdi.h" #elif defined(__WXGTK20__) #include "wx/gtk/mdi.h" #elif defined(__WXGTK__) @@ -30,11 +365,38 @@ #include "wx/osx/mdi.h" #elif defined(__WXCOCOA__) #include "wx/cocoa/mdi.h" -#elif defined(__WXPM__) - #include "wx/generic/mdig.h" #endif +inline wxMDIClientWindow *wxMDIParentFrameBase::OnCreateClient() +{ + return new wxMDIClientWindow; +} + +inline bool wxMDIParentFrameBase::TryBefore(wxEvent& event) +{ + // Menu (and toolbar) events should be sent to the active child frame + // first, if any. + if ( event.GetEventType() == wxEVT_MENU || + event.GetEventType() == wxEVT_UPDATE_UI ) + { + wxMDIChildFrame * const child = GetActiveChild(); + if ( child ) + { + // However avoid sending the event back to the child if it's + // currently being propagated to us from it. + wxWindow* const + from = static_cast(event.GetPropagatedFrom()); + if ( !from || !from->IsDescendant(child) ) + { + if ( child->ProcessWindowEventLocally(event) ) + return true; + } + } + } + + return wxFrame::TryBefore(event); +} + #endif // wxUSE_MDI -#endif - // _WX_MDI_H_BASE_ +#endif // _WX_MDI_H_BASE_