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