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