Added implementation of MDI using top level windows

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@24546 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
David Elliott 2003-11-13 16:03:08 +00:00
parent 3905012063
commit f99422e9e9
2 changed files with 498 additions and 0 deletions

163
include/wx/cocoa/mdi.h Normal file
View File

@ -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__

335
src/cocoa/mdi.mm Normal file
View File

@ -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;
}