]> git.saurik.com Git - wxWidgets.git/blob - src/cocoa/mdi.mm
minor tab height bug fix
[wxWidgets.git] / src / cocoa / mdi.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/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
9 // Licence: wxWidgets licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #if wxUSE_MDI
15
16 #include "wx/mdi.h"
17
18 #ifndef WX_PRECOMP
19 #include "wx/log.h"
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
30 #include "wx/listimpl.cpp"
31 WX_DEFINE_LIST(wxCocoaMDIChildFrameList);
32
33 WX_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 {
51 wxFAIL_MSG(wxT("[wxMDIParentFrameObserver -init] should never be called!"));
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 // ========================================================================
74 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame,wxFrame)
75 BEGIN_EVENT_TABLE(wxMDIParentFrame,wxFrame)
76 END_EVENT_TABLE()
77
78 void 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
89 bool 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
100 wxMDIParentFrame::~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
114 void wxMDIParentFrame::AddMDIChild(wxMDIChildFrame *child)
115 {
116 m_mdiChildren.Append(child);
117 }
118
119 void wxMDIParentFrame::RemoveMDIChild(wxMDIChildFrame *child)
120 {
121 m_mdiChildren.DeleteObject(child);
122 if(child==m_currentChild)
123 SetActiveChild(NULL);
124 }
125
126 wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
127 {
128 return m_currentChild;
129 }
130
131 void wxMDIParentFrame::SetActiveChild(wxMDIChildFrame *child)
132 {
133 m_currentChild = child;
134 wxMenuBarManager::GetInstance()->UpdateMenuBar();
135 }
136
137 wxMDIClientWindow *wxMDIParentFrame::GetClientWindow() const
138 {
139 return m_clientWindow;
140 }
141
142 wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
143 {
144 m_clientWindow = new wxMDIClientWindow( this );
145 return m_clientWindow;
146 }
147
148 void wxMDIParentFrame::ActivateNext()
149 {
150 }
151
152 void wxMDIParentFrame::ActivatePrevious()
153 {
154 }
155
156 wxMenuBar *wxMDIParentFrame::GetAppMenuBar(wxCocoaNSWindow *win)
157 {
158 if(m_currentChild && (win==this))
159 return m_currentChild->GetAppMenuBar(win);
160 return wxFrame::GetAppMenuBar(win);
161 }
162
163 void wxMDIParentFrame::CocoaDelegate_windowDidBecomeKey(void)
164 {
165 wxLogTrace(wxTRACE_COCOA,wxT("wxMDIParentFrame=%p::CocoaDelegate_windowDidBecomeKey"),this);
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
188 void wxMDIParentFrame::CocoaDelegate_windowDidResignKey(void)
189 {
190 wxLogTrace(wxTRACE_COCOA,wxT("wxMDIParentFrame=%p::CocoaDelegate_windowDidResignKey"),this);
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
199 bool wxMDIParentFrame::Cocoa_canBecomeMainWindow(bool &canBecome)
200 {
201 canBecome = m_mdiChildren.IsEmpty(); return true;
202 }
203
204 void 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 // ========================================================================
252 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame,wxFrame)
253 BEGIN_EVENT_TABLE(wxMDIChildFrame,wxFrame)
254 END_EVENT_TABLE()
255
256 void wxMDIChildFrame::Init()
257 {
258 m_mdiParent = NULL;
259 }
260
261 bool 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
275 wxMDIChildFrame::~wxMDIChildFrame()
276 {
277 // Just in case Destroy() wasn't called
278 m_mdiParent->RemoveMDIChild(this);
279 }
280
281 void wxMDIChildFrame::Activate()
282 {
283 }
284
285 void wxMDIChildFrame::CocoaDelegate_windowDidBecomeKey(void)
286 {
287 wxLogTrace(wxTRACE_COCOA,wxT("wxMDIChildFrame=%p::CocoaDelegate_windowDidBecomeKey"),this);
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
298 void wxMDIChildFrame::CocoaDelegate_windowDidBecomeMain(void)
299 {
300 m_mdiParent->SetActiveChild(this);
301 wxFrame::CocoaDelegate_windowDidBecomeMain();
302 }
303
304 void wxMDIChildFrame::CocoaDelegate_windowDidResignKey(void)
305 {
306 wxLogTrace(wxTRACE_COCOA,wxT("wxMDIChildFrame=%p::CocoaDelegate_windowDidResignKey"),this);
307 sm_cocoaDeactivateWindow = this;
308 }
309
310 bool 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 // ========================================================================
320 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow,wxWindow)
321
322 wxMDIClientWindow::wxMDIClientWindow()
323 {
324 }
325
326 wxMDIClientWindow::wxMDIClientWindow(wxMDIParentFrame *parent, long style)
327 :wxWindow(parent, wxID_ANY)
328 {
329 }
330
331 wxMDIClientWindow::~wxMDIClientWindow()
332 {
333 }
334
335 bool wxMDIClientWindow::CreateClient( wxMDIParentFrame *parent, long style)
336 {
337 return false;
338 }
339
340 #endif