]> git.saurik.com Git - wxWidgets.git/commitdiff
Added implementation of MDI using top level windows
authorDavid Elliott <dfe@tgwbd.org>
Thu, 13 Nov 2003 16:03:08 +0000 (16:03 +0000)
committerDavid Elliott <dfe@tgwbd.org>
Thu, 13 Nov 2003 16:03:08 +0000 (16:03 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@24546 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/cocoa/mdi.h [new file with mode: 0644]
src/cocoa/mdi.mm [new file with mode: 0644]

diff --git a/include/wx/cocoa/mdi.h b/include/wx/cocoa/mdi.h
new file mode 100644 (file)
index 0000000..e2e3b6e
--- /dev/null
@@ -0,0 +1,163 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wx/cocoa/mdi.h
+// Purpose:     wxMDIParentFrame, wxMDIChildFrame, wxMDIClientWindow
+// Author:      David Elliott
+// Modified by:
+// Created:     2003/09/08
+// RCS-ID:      $Id$
+// Copyright:   (c) 2003 David Elliott
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __WX_COCOA_MDI_H__
+#define __WX_COCOA_MDI_H__
+
+#include "wx/frame.h"
+
+DECLARE_WXCOCOA_OBJC_CLASS(wxMDIParentFrameObserver);
+
+class WXDLLEXPORT wxMDIChildFrame;
+class WXDLLEXPORT wxMDIClientWindow;
+
+WX_DECLARE_LIST(wxMDIChildFrame, wxCocoaMDIChildFrameList);
+
+// ========================================================================
+// wxMDIParentFrame
+// ========================================================================
+class WXDLLEXPORT wxMDIParentFrame: public wxFrame
+{
+    friend class WXDLLEXPORT wxMDIChildFrame;
+    DECLARE_EVENT_TABLE()
+    DECLARE_DYNAMIC_CLASS(wxMDIParentFrame)
+// ------------------------------------------------------------------------
+// initialization
+// ------------------------------------------------------------------------
+public:
+    wxMDIParentFrame() { Init(); }
+    wxMDIParentFrame(wxWindow *parent,
+            wxWindowID winid,
+            const wxString& title,
+            const wxPoint& pos = wxDefaultPosition,
+            const wxSize& size = wxDefaultSize,
+            long style = wxDEFAULT_FRAME_STYLE,
+            const wxString& name = wxFrameNameStr)
+    {
+        Init();
+        Create(parent, winid, title, pos, size, style, name);
+    }
+
+    virtual ~wxMDIParentFrame();
+
+    bool Create(wxWindow *parent,
+                wxWindowID winid,
+                const wxString& title,
+                const wxPoint& pos = wxDefaultPosition,
+                const wxSize& size = wxDefaultSize,
+                long style = wxDEFAULT_FRAME_STYLE,
+                const wxString& name = wxFrameNameStr);
+protected:
+    void Init();
+// ------------------------------------------------------------------------
+// Cocoa specifics
+// ------------------------------------------------------------------------
+public:
+    void WindowDidBecomeMain(NSNotification *notification);
+protected:
+    virtual void CocoaDelegate_windowDidBecomeKey(void);
+    virtual void CocoaDelegate_windowDidResignKey(void);
+    virtual bool Cocoa_canBecomeMainWindow(bool &canBecome);
+    virtual wxMenuBar* GetAppMenuBar(wxCocoaNSWindow *win);
+
+    void AddMDIChild(wxMDIChildFrame *child);
+    void RemoveMDIChild(wxMDIChildFrame *child);
+
+    wxMDIParentFrameObserver *m_observer;
+// ------------------------------------------------------------------------
+// Implementation
+// ------------------------------------------------------------------------
+public:
+    wxMDIChildFrame *GetActiveChild() const;
+    void SetActiveChild(wxMDIChildFrame *child);
+
+    wxMDIClientWindow *GetClientWindow() const;
+    virtual wxMDIClientWindow *OnCreateClient();
+
+    virtual void Cascade() {}
+    virtual void Tile() {}
+    virtual void ArrangeIcons() {}
+    virtual void ActivateNext();
+    virtual void ActivatePrevious();
+protected:
+    wxMDIClientWindow *m_clientWindow;
+    wxMDIChildFrame *m_currentChild;
+    wxCocoaMDIChildFrameList m_mdiChildren;
+};
+
+// ========================================================================
+// wxMDIChildFrame
+// ========================================================================
+class WXDLLEXPORT wxMDIChildFrame: public wxFrame
+{
+    friend class WXDLLEXPORT wxMDIParentFrame;
+    DECLARE_EVENT_TABLE()
+    DECLARE_DYNAMIC_CLASS(wxMDIChildFrame)
+// ------------------------------------------------------------------------
+// initialization
+// ------------------------------------------------------------------------
+public:
+    wxMDIChildFrame() { Init(); }
+    wxMDIChildFrame(wxMDIParentFrame *parent,
+            wxWindowID winid,
+            const wxString& title,
+            const wxPoint& pos = wxDefaultPosition,
+            const wxSize& size = wxDefaultSize,
+            long style = wxDEFAULT_FRAME_STYLE,
+            const wxString& name = wxFrameNameStr)
+    {
+        Init();
+        Create(parent, winid, title, pos, size, style, name);
+    }
+
+    virtual ~wxMDIChildFrame();
+
+    bool Create(wxMDIParentFrame *parent,
+                wxWindowID winid,
+                const wxString& title,
+                const wxPoint& pos = wxDefaultPosition,
+                const wxSize& size = wxDefaultSize,
+                long style = wxDEFAULT_FRAME_STYLE,
+                const wxString& name = wxFrameNameStr);
+protected:
+    void Init();
+// ------------------------------------------------------------------------
+// Cocoa specifics
+// ------------------------------------------------------------------------
+public:
+protected:
+    virtual void CocoaDelegate_windowDidBecomeKey(void);
+    virtual void CocoaDelegate_windowDidBecomeMain(void);
+    virtual void CocoaDelegate_windowDidResignKey(void);
+// ------------------------------------------------------------------------
+// Implementation
+// ------------------------------------------------------------------------
+public:
+    virtual void Activate();
+    virtual bool Destroy();
+protected:
+    wxMDIParentFrame *m_mdiParent;
+};
+
+// ========================================================================
+// wxMDIClientWindow
+// ========================================================================
+class wxMDIClientWindow: public wxWindow
+{
+    DECLARE_DYNAMIC_CLASS(wxMDIClientWindow)
+public:
+    wxMDIClientWindow();
+    wxMDIClientWindow( wxMDIParentFrame *parent, long style = 0 );
+    ~wxMDIClientWindow();
+    virtual bool CreateClient( wxMDIParentFrame *parent, long style = 0 );
+};
+
+#endif // __WX_COCOA_MDI_H__
diff --git a/src/cocoa/mdi.mm b/src/cocoa/mdi.mm
new file mode 100644 (file)
index 0000000..1d069d5
--- /dev/null
@@ -0,0 +1,335 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        cocoa/mdi.mm
+// Purpose:     wxMDIParentFrame, wxMDIChildFrame, wxMDIClientWindow
+// Author:      David Elliott
+// Modified by:
+// Created:     2003/09/08
+// RCS-ID:      $Id$
+// Copyright:   (c) 2003 David Elliott
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+#ifndef WX_PRECOMP
+    #include "wx/log.h"
+    #include "wx/mdi.h"
+#endif // WX_PRECOMP
+
+// #include "wx/cocoa/autorelease.h"
+#include "wx/cocoa/mbarman.h"
+
+#import <AppKit/NSWindow.h>
+#import <Foundation/NSNotification.h>
+// #import <AppKit/NSApplication.h>
+// #import <AppKit/NSView.h>
+
+#include <wx/listimpl.cpp>
+WX_DEFINE_LIST(wxCocoaMDIChildFrameList);
+
+WX_DECLARE_HASH_MAP(int, wxMDIChildFrame*, wxIntegerHash, wxIntegerEqual, wxIntMDIChildFrameHashMap);
+
+// ============================================================================
+// wxMDIParentFrameObserver
+// ============================================================================
+@interface wxMDIParentFrameObserver : NSObject
+{
+    wxMDIParentFrame *m_mdiParent;
+}
+
+- (id)init;
+- (id)initWithWxMDIParentFrame: (wxMDIParentFrame *)mdiParent;
+- (void)windowDidBecomeMain: (NSNotification *)notification;
+@end // interface wxMDIParentFrameObserver : NSObject
+
+@implementation wxMDIParentFrameObserver : NSObject
+- (id)init
+{
+    wxFAIL_MSG("[wxMDIParentFrameObserver -init] should never be called!");
+    m_mdiParent = NULL;
+    return self;
+}
+
+- (id)initWithWxMDIParentFrame: (wxMDIParentFrame *)mdiParent
+{
+    wxASSERT(mdiParent);
+    m_mdiParent = mdiParent;
+    return [super init];
+}
+
+- (void)windowDidBecomeMain: (NSNotification *)notification
+{
+    wxASSERT(m_mdiParent);
+    m_mdiParent->WindowDidBecomeMain(notification);
+}
+
+@end // implementation wxMDIParentFrameObserver : NSObject
+
+// ========================================================================
+// wxMDIParentFrame
+// ========================================================================
+IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame,wxFrame)
+BEGIN_EVENT_TABLE(wxMDIParentFrame,wxFrame)
+END_EVENT_TABLE()
+
+void wxMDIParentFrame::Init()
+{
+    m_clientWindow = NULL;
+    m_currentChild = NULL;
+    m_observer = [[wxMDIParentFrameObserver alloc]
+            initWithWxMDIParentFrame:this];
+    [[NSNotificationCenter defaultCenter] addObserver:m_observer
+            selector:@selector(windowDidBecomeMain:)
+            name:NSWindowDidBecomeMainNotification object:nil];
+}
+
+bool wxMDIParentFrame::Create(wxWindow *parent,
+        wxWindowID winid, const wxString& title,
+        const wxPoint& pos, const wxSize& size,
+        long style, const wxString& name)
+{
+    bool success = wxFrame::Create(parent,winid,title,pos,size,style,name);
+    if(success)
+        OnCreateClient();
+    return success;
+}
+
+wxMDIParentFrame::~wxMDIParentFrame()
+{
+    for(wxCocoaMDIChildFrameList::compatibility_iterator node =
+            m_mdiChildren.GetFirst(); node; node = m_mdiChildren.GetFirst())
+    {
+        wxMDIChildFrame *child = node->GetData();
+        // Delete it NOW
+        delete child;
+        wxASSERT_MSG(!m_mdiChildren.Find(child),
+            wxT("MDI child didn't remove itself using RemoveMDIChild()"));
+    }
+    [m_observer release];
+}
+
+void wxMDIParentFrame::AddMDIChild(wxMDIChildFrame *child)
+{
+    m_mdiChildren.Append(child);
+}
+
+void wxMDIParentFrame::RemoveMDIChild(wxMDIChildFrame *child)
+{
+    m_mdiChildren.DeleteObject(child);
+    if(child==m_currentChild)
+        SetActiveChild(NULL);
+}
+
+wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
+{
+    return m_currentChild;
+}
+
+void wxMDIParentFrame::SetActiveChild(wxMDIChildFrame *child)
+{
+    m_currentChild = child;
+    wxMenuBarManager::GetInstance()->UpdateMenuBar();
+}
+
+wxMDIClientWindow *wxMDIParentFrame::GetClientWindow() const
+{
+    return m_clientWindow;
+}
+
+wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
+{
+    m_clientWindow = new wxMDIClientWindow( this );
+    return m_clientWindow;
+}
+
+void wxMDIParentFrame::ActivateNext()
+{
+}
+
+void wxMDIParentFrame::ActivatePrevious()
+{
+}
+
+wxMenuBar *wxMDIParentFrame::GetAppMenuBar(wxCocoaNSWindow *win)
+{
+    if(m_currentChild && (win==this))
+        return m_currentChild->GetAppMenuBar(win);
+    return wxFrame::GetAppMenuBar(win);
+}
+
+void wxMDIParentFrame::CocoaDelegate_windowDidBecomeKey(void)
+{
+    wxLogDebug("wxMDIParentFrame=%p::CocoaDelegate_windowDidBecomeKey",this);
+    if(sm_cocoaDeactivateWindow && sm_cocoaDeactivateWindow==m_currentChild)
+    {
+        sm_cocoaDeactivateWindow = NULL;
+    }
+    #if 0
+    else if(sm_cocoaDeactivateWindow == this)
+    {
+        sm_cocoaDeactivateWindow = NULL;
+    }
+    #endif
+    else
+    {
+        if(m_currentChild)
+        {
+            NSWindow *nswin = m_currentChild->GetNSWindow();
+            if(![nswin isMainWindow])
+                [nswin makeMainWindow];
+        }
+        wxFrame::CocoaDelegate_windowDidBecomeKey();
+    }
+}
+
+void wxMDIParentFrame::CocoaDelegate_windowDidResignKey(void)
+{
+    wxLogDebug("wxMDIParentFrame=%p::CocoaDelegate_windowDidResignKey",this);
+    if(m_closed)
+        wxFrame::CocoaDelegate_windowDidResignKey();
+    else
+        sm_cocoaDeactivateWindow = this;
+}
+
+// We should not become the main window as we aren't a document window
+// MDI "Children" should be the main window
+bool wxMDIParentFrame::Cocoa_canBecomeMainWindow(bool &canBecome)
+{
+    canBecome = m_mdiChildren.IsEmpty(); return true;
+}
+
+void wxMDIParentFrame::WindowDidBecomeMain(NSNotification *notification)
+{
+    // If we aren't the key window, we don't care
+    if(![m_cocoaNSWindow isKeyWindow])
+        return;
+    wxCocoaNSWindow *win = wxCocoaNSWindow::GetFromCocoa([notification object]);
+    // If we are key and becoming main, that's great
+    if(win==this)
+        return;
+    // If one of our children is becoming main, also great
+    for(wxCocoaMDIChildFrameList::compatibility_iterator node =
+            m_mdiChildren.GetFirst(); node; node = node->GetNext())
+    {
+        wxMDIChildFrame *child = node->GetData();
+        if(win==child)
+            return;
+    }
+    // Some other window is becoming main, but we are key
+    // Make the new main window the key window
+    [[notification object] makeKeyWindow];
+    if(!m_currentChild)
+    {
+        wxIntMDIChildFrameHashMap hashmap;
+        for(wxCocoaMDIChildFrameList::compatibility_iterator node =
+                m_mdiChildren.GetFirst(); node; node = node->GetNext())
+        {
+            wxMDIChildFrame *child = node->GetData();
+            hashmap.insert(wxIntMDIChildFrameHashMap::value_type([child->m_cocoaNSWindow windowNumber],child));
+        }
+        if(!hashmap.empty())
+        {
+            int windowCount = 0;
+            NSCountWindows(&windowCount);
+            wxASSERT(windowCount>0);
+            int *windowList = new int[windowCount];
+            NSWindowList(windowCount, windowList);
+            wxIntMDIChildFrameHashMap::iterator iter = hashmap.end();
+            for(int i=0; i<windowCount && iter == hashmap.end(); i++)
+                iter=hashmap.find(windowList[i]);
+            if(iter != hashmap.end())
+                m_currentChild = iter->second;
+        }
+    }
+}
+
+// ========================================================================
+// wxMDIChildFrame
+// ========================================================================
+IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame,wxFrame)
+BEGIN_EVENT_TABLE(wxMDIChildFrame,wxFrame)
+END_EVENT_TABLE()
+
+void wxMDIChildFrame::Init()
+{
+    m_mdiParent = NULL;
+}
+
+bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
+        wxWindowID winid, const wxString& title,
+        const wxPoint& pos, const wxSize& size,
+        long style, const wxString& name)
+{
+    bool success = wxFrame::Create(parent,winid,title,pos,size,style,name);
+    if(success)
+    {
+        m_mdiParent = parent;
+        parent->AddMDIChild(this);
+    }
+    return success;
+}
+
+wxMDIChildFrame::~wxMDIChildFrame()
+{
+    // Just in case Destroy() wasn't called
+    m_mdiParent->RemoveMDIChild(this);
+}
+
+void wxMDIChildFrame::Activate()
+{
+}
+
+void wxMDIChildFrame::CocoaDelegate_windowDidBecomeKey(void)
+{
+    wxLogDebug("wxMDIChildFrame=%p::CocoaDelegate_windowDidBecomeKey",this);
+    if(sm_cocoaDeactivateWindow && sm_cocoaDeactivateWindow==m_mdiParent)
+    {
+        sm_cocoaDeactivateWindow = NULL;
+        if(m_mdiParent->GetActiveChild() != this)
+            sm_cocoaDeactivateWindow = m_mdiParent->GetActiveChild();
+    }
+    m_mdiParent->SetActiveChild(this);
+    wxFrame::CocoaDelegate_windowDidBecomeKey();
+}
+
+void wxMDIChildFrame::CocoaDelegate_windowDidBecomeMain(void)
+{
+    m_mdiParent->SetActiveChild(this);
+    wxFrame::CocoaDelegate_windowDidBecomeMain();
+}
+
+void wxMDIChildFrame::CocoaDelegate_windowDidResignKey(void)
+{
+    wxLogDebug("wxMDIChildFrame=%p::CocoaDelegate_windowDidResignKey",this);
+    sm_cocoaDeactivateWindow = this;
+}
+
+bool wxMDIChildFrame::Destroy()
+{
+    // It's good to do this here before we are really closed
+    m_mdiParent->RemoveMDIChild(this);
+    return wxFrame::Destroy();
+}
+
+// ========================================================================
+// wxMDIClientWindow
+// ========================================================================
+IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow,wxWindow)
+
+wxMDIClientWindow::wxMDIClientWindow()
+{
+}
+
+wxMDIClientWindow::wxMDIClientWindow(wxMDIParentFrame *parent, long style)
+:   wxWindow(parent, -1)
+{
+}
+
+wxMDIClientWindow::~wxMDIClientWindow()
+{
+}
+
+bool wxMDIClientWindow::CreateClient( wxMDIParentFrame *parent, long style)
+{
+    return false;
+}
+