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