/////////////////////////////////////////////////////////////////////////////
// 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
/////////////////////////////////////////////////////////////////////////////
#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__)
#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<wxWindow*>(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_