]> git.saurik.com Git - wxWidgets.git/blame - src/cocoa/mdi.mm
new file added
[wxWidgets.git] / src / cocoa / mdi.mm
CommitLineData
f99422e9 1/////////////////////////////////////////////////////////////////////////////
59cf2e49 2// Name: src/cocoa/mdi.mm
f99422e9
DE
3// Purpose: wxMDIParentFrame, wxMDIChildFrame, wxMDIClientWindow
4// Author: David Elliott
5// Modified by:
6// Created: 2003/09/08
7// RCS-ID: $Id$
8// Copyright: (c) 2003 David Elliott
526954c5 9// Licence: wxWindows licence
f99422e9
DE
10/////////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
16c81607
RN
13
14#if wxUSE_MDI
15
59cf2e49
WS
16#include "wx/mdi.h"
17
e7e1ad7d
DE
18#include "wx/cocoa/objc/objc_uniquifying.h"
19
f99422e9
DE
20#ifndef WX_PRECOMP
21 #include "wx/log.h"
f99422e9
DE
22#endif // WX_PRECOMP
23
24// #include "wx/cocoa/autorelease.h"
25#include "wx/cocoa/mbarman.h"
26
27#import <AppKit/NSWindow.h>
28#import <Foundation/NSNotification.h>
29// #import <AppKit/NSApplication.h>
30// #import <AppKit/NSView.h>
31
d8418952 32#include "wx/listimpl.cpp"
f99422e9
DE
33WX_DEFINE_LIST(wxCocoaMDIChildFrameList);
34
35WX_DECLARE_HASH_MAP(int, wxMDIChildFrame*, wxIntegerHash, wxIntegerEqual, wxIntMDIChildFrameHashMap);
36
37// ============================================================================
38// wxMDIParentFrameObserver
39// ============================================================================
40@interface wxMDIParentFrameObserver : NSObject
41{
42 wxMDIParentFrame *m_mdiParent;
43}
44
45- (id)init;
46- (id)initWithWxMDIParentFrame: (wxMDIParentFrame *)mdiParent;
47- (void)windowDidBecomeMain: (NSNotification *)notification;
48@end // interface wxMDIParentFrameObserver : NSObject
e7e1ad7d 49WX_DECLARE_GET_OBJC_CLASS(wxMDIParentFrameObserver,NSObject)
f99422e9
DE
50
51@implementation wxMDIParentFrameObserver : NSObject
52- (id)init
53{
2b030203 54 wxFAIL_MSG(wxT("[wxMDIParentFrameObserver -init] should never be called!"));
f99422e9
DE
55 m_mdiParent = NULL;
56 return self;
57}
58
59- (id)initWithWxMDIParentFrame: (wxMDIParentFrame *)mdiParent
60{
61 wxASSERT(mdiParent);
62 m_mdiParent = mdiParent;
63 return [super init];
64}
65
66- (void)windowDidBecomeMain: (NSNotification *)notification
67{
68 wxASSERT(m_mdiParent);
69 m_mdiParent->WindowDidBecomeMain(notification);
70}
71
72@end // implementation wxMDIParentFrameObserver : NSObject
e7e1ad7d 73WX_IMPLEMENT_GET_OBJC_CLASS(wxMDIParentFrameObserver,NSObject)
f99422e9
DE
74
75// ========================================================================
76// wxMDIParentFrame
77// ========================================================================
78IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame,wxFrame)
79BEGIN_EVENT_TABLE(wxMDIParentFrame,wxFrame)
80END_EVENT_TABLE()
81
82void wxMDIParentFrame::Init()
83{
84 m_clientWindow = NULL;
85 m_currentChild = NULL;
e7e1ad7d 86 m_observer = [[WX_GET_OBJC_CLASS(wxMDIParentFrameObserver) alloc]
f99422e9
DE
87 initWithWxMDIParentFrame:this];
88 [[NSNotificationCenter defaultCenter] addObserver:m_observer
89 selector:@selector(windowDidBecomeMain:)
90 name:NSWindowDidBecomeMainNotification object:nil];
91}
92
93bool wxMDIParentFrame::Create(wxWindow *parent,
94 wxWindowID winid, const wxString& title,
95 const wxPoint& pos, const wxSize& size,
96 long style, const wxString& name)
97{
6e42617a
VZ
98 if ( !wxFrame::Create(parent,winid,title,pos,size,style,name) )
99 return false;
100
101 m_clientWindow = OnCreateClient();
102
103 return m_clientWindow != NULL;
f99422e9
DE
104}
105
106wxMDIParentFrame::~wxMDIParentFrame()
107{
108 for(wxCocoaMDIChildFrameList::compatibility_iterator node =
109 m_mdiChildren.GetFirst(); node; node = m_mdiChildren.GetFirst())
110 {
111 wxMDIChildFrame *child = node->GetData();
112 // Delete it NOW
113 delete child;
114 wxASSERT_MSG(!m_mdiChildren.Find(child),
115 wxT("MDI child didn't remove itself using RemoveMDIChild()"));
116 }
117 [m_observer release];
118}
119
120void wxMDIParentFrame::AddMDIChild(wxMDIChildFrame *child)
121{
122 m_mdiChildren.Append(child);
123}
124
125void wxMDIParentFrame::RemoveMDIChild(wxMDIChildFrame *child)
126{
127 m_mdiChildren.DeleteObject(child);
128 if(child==m_currentChild)
129 SetActiveChild(NULL);
130}
131
f99422e9
DE
132void wxMDIParentFrame::SetActiveChild(wxMDIChildFrame *child)
133{
134 m_currentChild = child;
135 wxMenuBarManager::GetInstance()->UpdateMenuBar();
136}
137
f99422e9
DE
138wxMenuBar *wxMDIParentFrame::GetAppMenuBar(wxCocoaNSWindow *win)
139{
140 if(m_currentChild && (win==this))
141 return m_currentChild->GetAppMenuBar(win);
142 return wxFrame::GetAppMenuBar(win);
143}
144
145void wxMDIParentFrame::CocoaDelegate_windowDidBecomeKey(void)
146{
48580976 147 wxLogTrace(wxTRACE_COCOA,wxT("wxMDIParentFrame=%p::CocoaDelegate_windowDidBecomeKey"),this);
f99422e9
DE
148 if(sm_cocoaDeactivateWindow && sm_cocoaDeactivateWindow==m_currentChild)
149 {
150 sm_cocoaDeactivateWindow = NULL;
151 }
152 #if 0
153 else if(sm_cocoaDeactivateWindow == this)
154 {
155 sm_cocoaDeactivateWindow = NULL;
156 }
157 #endif
158 else
159 {
160 if(m_currentChild)
161 {
162 NSWindow *nswin = m_currentChild->GetNSWindow();
163 if(![nswin isMainWindow])
164 [nswin makeMainWindow];
165 }
166 wxFrame::CocoaDelegate_windowDidBecomeKey();
167 }
168}
169
170void wxMDIParentFrame::CocoaDelegate_windowDidResignKey(void)
171{
48580976 172 wxLogTrace(wxTRACE_COCOA,wxT("wxMDIParentFrame=%p::CocoaDelegate_windowDidResignKey"),this);
f99422e9
DE
173 if(m_closed)
174 wxFrame::CocoaDelegate_windowDidResignKey();
175 else
176 sm_cocoaDeactivateWindow = this;
177}
178
179// We should not become the main window as we aren't a document window
180// MDI "Children" should be the main window
181bool wxMDIParentFrame::Cocoa_canBecomeMainWindow(bool &canBecome)
182{
183 canBecome = m_mdiChildren.IsEmpty(); return true;
184}
185
186void wxMDIParentFrame::WindowDidBecomeMain(NSNotification *notification)
187{
188 // If we aren't the key window, we don't care
189 if(![m_cocoaNSWindow isKeyWindow])
190 return;
191 wxCocoaNSWindow *win = wxCocoaNSWindow::GetFromCocoa([notification object]);
192 // If we are key and becoming main, that's great
193 if(win==this)
194 return;
195 // If one of our children is becoming main, also great
196 for(wxCocoaMDIChildFrameList::compatibility_iterator node =
197 m_mdiChildren.GetFirst(); node; node = node->GetNext())
198 {
199 wxMDIChildFrame *child = node->GetData();
200 if(win==child)
201 return;
202 }
203 // Some other window is becoming main, but we are key
204 // Make the new main window the key window
205 [[notification object] makeKeyWindow];
206 if(!m_currentChild)
207 {
208 wxIntMDIChildFrameHashMap hashmap;
209 for(wxCocoaMDIChildFrameList::compatibility_iterator node =
210 m_mdiChildren.GetFirst(); node; node = node->GetNext())
211 {
212 wxMDIChildFrame *child = node->GetData();
213 hashmap.insert(wxIntMDIChildFrameHashMap::value_type([child->m_cocoaNSWindow windowNumber],child));
214 }
215 if(!hashmap.empty())
216 {
4799f3ba 217 NSInteger windowCount = 0;
f99422e9
DE
218 NSCountWindows(&windowCount);
219 wxASSERT(windowCount>0);
4799f3ba 220 NSInteger *windowList = new NSInteger[windowCount];
f99422e9
DE
221 NSWindowList(windowCount, windowList);
222 wxIntMDIChildFrameHashMap::iterator iter = hashmap.end();
223 for(int i=0; i<windowCount && iter == hashmap.end(); i++)
224 iter=hashmap.find(windowList[i]);
225 if(iter != hashmap.end())
226 m_currentChild = iter->second;
227 }
228 }
229}
230
231// ========================================================================
232// wxMDIChildFrame
233// ========================================================================
234IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame,wxFrame)
235BEGIN_EVENT_TABLE(wxMDIChildFrame,wxFrame)
236END_EVENT_TABLE()
237
238void wxMDIChildFrame::Init()
239{
240 m_mdiParent = NULL;
241}
242
243bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
244 wxWindowID winid, const wxString& title,
245 const wxPoint& pos, const wxSize& size,
246 long style, const wxString& name)
247{
248 bool success = wxFrame::Create(parent,winid,title,pos,size,style,name);
249 if(success)
250 {
251 m_mdiParent = parent;
252 parent->AddMDIChild(this);
253 }
254 return success;
255}
256
257wxMDIChildFrame::~wxMDIChildFrame()
258{
259 // Just in case Destroy() wasn't called
260 m_mdiParent->RemoveMDIChild(this);
261}
262
263void wxMDIChildFrame::Activate()
264{
265}
266
267void wxMDIChildFrame::CocoaDelegate_windowDidBecomeKey(void)
268{
48580976 269 wxLogTrace(wxTRACE_COCOA,wxT("wxMDIChildFrame=%p::CocoaDelegate_windowDidBecomeKey"),this);
f99422e9
DE
270 if(sm_cocoaDeactivateWindow && sm_cocoaDeactivateWindow==m_mdiParent)
271 {
272 sm_cocoaDeactivateWindow = NULL;
273 if(m_mdiParent->GetActiveChild() != this)
274 sm_cocoaDeactivateWindow = m_mdiParent->GetActiveChild();
275 }
276 m_mdiParent->SetActiveChild(this);
277 wxFrame::CocoaDelegate_windowDidBecomeKey();
278}
279
280void wxMDIChildFrame::CocoaDelegate_windowDidBecomeMain(void)
281{
282 m_mdiParent->SetActiveChild(this);
283 wxFrame::CocoaDelegate_windowDidBecomeMain();
284}
285
286void wxMDIChildFrame::CocoaDelegate_windowDidResignKey(void)
287{
48580976 288 wxLogTrace(wxTRACE_COCOA,wxT("wxMDIChildFrame=%p::CocoaDelegate_windowDidResignKey"),this);
f99422e9
DE
289 sm_cocoaDeactivateWindow = this;
290}
291
292bool wxMDIChildFrame::Destroy()
293{
294 // It's good to do this here before we are really closed
295 m_mdiParent->RemoveMDIChild(this);
296 return wxFrame::Destroy();
297}
298
299// ========================================================================
300// wxMDIClientWindow
301// ========================================================================
302IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow,wxWindow)
303
d2824cdb 304bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
f99422e9 305{
d2824cdb 306 return Create(parent, wxID_ANY, wxPoint(0, 0), wxSize(0, 0), style);
f99422e9
DE
307}
308
d2824cdb 309#endif // wxUSE_MDI