]> git.saurik.com Git - wxWidgets.git/blame - src/cocoa/mdi.mm
use less expensive GetLastPosition() instead of GetValue() to implement IsEmpty()
[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
065e208e 9// Licence: wxWidgets 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{
98 bool success = wxFrame::Create(parent,winid,title,pos,size,style,name);
99 if(success)
100 OnCreateClient();
101 return success;
102}
103
104wxMDIParentFrame::~wxMDIParentFrame()
105{
106 for(wxCocoaMDIChildFrameList::compatibility_iterator node =
107 m_mdiChildren.GetFirst(); node; node = m_mdiChildren.GetFirst())
108 {
109 wxMDIChildFrame *child = node->GetData();
110 // Delete it NOW
111 delete child;
112 wxASSERT_MSG(!m_mdiChildren.Find(child),
113 wxT("MDI child didn't remove itself using RemoveMDIChild()"));
114 }
115 [m_observer release];
116}
117
118void wxMDIParentFrame::AddMDIChild(wxMDIChildFrame *child)
119{
120 m_mdiChildren.Append(child);
121}
122
123void wxMDIParentFrame::RemoveMDIChild(wxMDIChildFrame *child)
124{
125 m_mdiChildren.DeleteObject(child);
126 if(child==m_currentChild)
127 SetActiveChild(NULL);
128}
129
130wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
131{
132 return m_currentChild;
133}
134
135void wxMDIParentFrame::SetActiveChild(wxMDIChildFrame *child)
136{
137 m_currentChild = child;
138 wxMenuBarManager::GetInstance()->UpdateMenuBar();
139}
140
141wxMDIClientWindow *wxMDIParentFrame::GetClientWindow() const
142{
143 return m_clientWindow;
144}
145
146wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
147{
148 m_clientWindow = new wxMDIClientWindow( this );
149 return m_clientWindow;
150}
151
152void wxMDIParentFrame::ActivateNext()
153{
154}
155
156void wxMDIParentFrame::ActivatePrevious()
157{
158}
159
160wxMenuBar *wxMDIParentFrame::GetAppMenuBar(wxCocoaNSWindow *win)
161{
162 if(m_currentChild && (win==this))
163 return m_currentChild->GetAppMenuBar(win);
164 return wxFrame::GetAppMenuBar(win);
165}
166
167void wxMDIParentFrame::CocoaDelegate_windowDidBecomeKey(void)
168{
48580976 169 wxLogTrace(wxTRACE_COCOA,wxT("wxMDIParentFrame=%p::CocoaDelegate_windowDidBecomeKey"),this);
f99422e9
DE
170 if(sm_cocoaDeactivateWindow && sm_cocoaDeactivateWindow==m_currentChild)
171 {
172 sm_cocoaDeactivateWindow = NULL;
173 }
174 #if 0
175 else if(sm_cocoaDeactivateWindow == this)
176 {
177 sm_cocoaDeactivateWindow = NULL;
178 }
179 #endif
180 else
181 {
182 if(m_currentChild)
183 {
184 NSWindow *nswin = m_currentChild->GetNSWindow();
185 if(![nswin isMainWindow])
186 [nswin makeMainWindow];
187 }
188 wxFrame::CocoaDelegate_windowDidBecomeKey();
189 }
190}
191
192void wxMDIParentFrame::CocoaDelegate_windowDidResignKey(void)
193{
48580976 194 wxLogTrace(wxTRACE_COCOA,wxT("wxMDIParentFrame=%p::CocoaDelegate_windowDidResignKey"),this);
f99422e9
DE
195 if(m_closed)
196 wxFrame::CocoaDelegate_windowDidResignKey();
197 else
198 sm_cocoaDeactivateWindow = this;
199}
200
201// We should not become the main window as we aren't a document window
202// MDI "Children" should be the main window
203bool wxMDIParentFrame::Cocoa_canBecomeMainWindow(bool &canBecome)
204{
205 canBecome = m_mdiChildren.IsEmpty(); return true;
206}
207
208void wxMDIParentFrame::WindowDidBecomeMain(NSNotification *notification)
209{
210 // If we aren't the key window, we don't care
211 if(![m_cocoaNSWindow isKeyWindow])
212 return;
213 wxCocoaNSWindow *win = wxCocoaNSWindow::GetFromCocoa([notification object]);
214 // If we are key and becoming main, that's great
215 if(win==this)
216 return;
217 // If one of our children is becoming main, also great
218 for(wxCocoaMDIChildFrameList::compatibility_iterator node =
219 m_mdiChildren.GetFirst(); node; node = node->GetNext())
220 {
221 wxMDIChildFrame *child = node->GetData();
222 if(win==child)
223 return;
224 }
225 // Some other window is becoming main, but we are key
226 // Make the new main window the key window
227 [[notification object] makeKeyWindow];
228 if(!m_currentChild)
229 {
230 wxIntMDIChildFrameHashMap hashmap;
231 for(wxCocoaMDIChildFrameList::compatibility_iterator node =
232 m_mdiChildren.GetFirst(); node; node = node->GetNext())
233 {
234 wxMDIChildFrame *child = node->GetData();
235 hashmap.insert(wxIntMDIChildFrameHashMap::value_type([child->m_cocoaNSWindow windowNumber],child));
236 }
237 if(!hashmap.empty())
238 {
4799f3ba 239 NSInteger windowCount = 0;
f99422e9
DE
240 NSCountWindows(&windowCount);
241 wxASSERT(windowCount>0);
4799f3ba 242 NSInteger *windowList = new NSInteger[windowCount];
f99422e9
DE
243 NSWindowList(windowCount, windowList);
244 wxIntMDIChildFrameHashMap::iterator iter = hashmap.end();
245 for(int i=0; i<windowCount && iter == hashmap.end(); i++)
246 iter=hashmap.find(windowList[i]);
247 if(iter != hashmap.end())
248 m_currentChild = iter->second;
249 }
250 }
251}
252
253// ========================================================================
254// wxMDIChildFrame
255// ========================================================================
256IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame,wxFrame)
257BEGIN_EVENT_TABLE(wxMDIChildFrame,wxFrame)
258END_EVENT_TABLE()
259
260void wxMDIChildFrame::Init()
261{
262 m_mdiParent = NULL;
263}
264
265bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
266 wxWindowID winid, const wxString& title,
267 const wxPoint& pos, const wxSize& size,
268 long style, const wxString& name)
269{
270 bool success = wxFrame::Create(parent,winid,title,pos,size,style,name);
271 if(success)
272 {
273 m_mdiParent = parent;
274 parent->AddMDIChild(this);
275 }
276 return success;
277}
278
279wxMDIChildFrame::~wxMDIChildFrame()
280{
281 // Just in case Destroy() wasn't called
282 m_mdiParent->RemoveMDIChild(this);
283}
284
285void wxMDIChildFrame::Activate()
286{
287}
288
289void wxMDIChildFrame::CocoaDelegate_windowDidBecomeKey(void)
290{
48580976 291 wxLogTrace(wxTRACE_COCOA,wxT("wxMDIChildFrame=%p::CocoaDelegate_windowDidBecomeKey"),this);
f99422e9
DE
292 if(sm_cocoaDeactivateWindow && sm_cocoaDeactivateWindow==m_mdiParent)
293 {
294 sm_cocoaDeactivateWindow = NULL;
295 if(m_mdiParent->GetActiveChild() != this)
296 sm_cocoaDeactivateWindow = m_mdiParent->GetActiveChild();
297 }
298 m_mdiParent->SetActiveChild(this);
299 wxFrame::CocoaDelegate_windowDidBecomeKey();
300}
301
302void wxMDIChildFrame::CocoaDelegate_windowDidBecomeMain(void)
303{
304 m_mdiParent->SetActiveChild(this);
305 wxFrame::CocoaDelegate_windowDidBecomeMain();
306}
307
308void wxMDIChildFrame::CocoaDelegate_windowDidResignKey(void)
309{
48580976 310 wxLogTrace(wxTRACE_COCOA,wxT("wxMDIChildFrame=%p::CocoaDelegate_windowDidResignKey"),this);
f99422e9
DE
311 sm_cocoaDeactivateWindow = this;
312}
313
314bool wxMDIChildFrame::Destroy()
315{
316 // It's good to do this here before we are really closed
317 m_mdiParent->RemoveMDIChild(this);
318 return wxFrame::Destroy();
319}
320
321// ========================================================================
322// wxMDIClientWindow
323// ========================================================================
324IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow,wxWindow)
325
326wxMDIClientWindow::wxMDIClientWindow()
327{
328}
329
330wxMDIClientWindow::wxMDIClientWindow(wxMDIParentFrame *parent, long style)
59cf2e49 331 :wxWindow(parent, wxID_ANY)
f99422e9
DE
332{
333}
334
335wxMDIClientWindow::~wxMDIClientWindow()
336{
337}
338
339bool wxMDIClientWindow::CreateClient( wxMDIParentFrame *parent, long style)
340{
341 return false;
342}
343
16c81607 344#endif