]> git.saurik.com Git - wxWidgets.git/blob - src/cocoa/toplevel.mm
wxMenuBarManager::InstallMenuBarForWindow no longer looks for a menubar
[wxWidgets.git] / src / cocoa / toplevel.mm
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: cocoa/toplevel.mm
3 // Purpose: implements wxTopLevelWindow for Cocoa
4 // Author: David Elliott
5 // Modified by:
6 // Created: 2002/11/27
7 // RCS-ID: $Id:
8 // Copyright: (c) 2002 David Elliott
9 // License: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22 #ifndef WX_PRECOMP
23 #include "wx/window.h"
24 #include "wx/toplevel.h"
25 #include "wx/menuitem.h"
26 #include "wx/frame.h"
27 #include "wx/log.h"
28 #include "wx/app.h"
29 #endif //WX_PRECOMP
30
31 #include "wx/cocoa/autorelease.h"
32 #include "wx/cocoa/string.h"
33 #include "wx/cocoa/mbarman.h"
34
35 #import <AppKit/NSView.h>
36 #import <AppKit/NSWindow.h>
37 #import <AppKit/NSPanel.h>
38 // ----------------------------------------------------------------------------
39 // globals
40 // ----------------------------------------------------------------------------
41
42 // list of all frames and modeless dialogs
43 wxWindowList wxModelessWindows;
44
45 // ============================================================================
46 // wxTopLevelWindowCocoa implementation
47 // ============================================================================
48
49 // ----------------------------------------------------------------------------
50 // wxTopLevelWindowCocoa creation
51 // ----------------------------------------------------------------------------
52 BEGIN_EVENT_TABLE(wxTopLevelWindowCocoa,wxTopLevelWindowBase)
53 EVT_CLOSE(wxTopLevelWindowCocoa::OnCloseWindow)
54 END_EVENT_TABLE()
55
56 void wxTopLevelWindowCocoa::Init()
57 {
58 m_iconized =
59 m_maximizeOnShow =
60 m_closed = false;
61 }
62
63 unsigned int wxTopLevelWindowCocoa::NSWindowStyleForWxStyle(long style)
64 {
65 unsigned int styleMask = 0;
66 if(style & wxCAPTION)
67 styleMask |= NSTitledWindowMask;
68 if(style & wxMINIMIZE_BOX)
69 styleMask |= NSMiniaturizableWindowMask;
70 #if 0
71 if(style & wxMAXIMIZE_BOX)
72 styleMask |= NSWindowMask;
73 #endif
74 if(style & wxCLOSE_BOX)
75 styleMask |= NSClosableWindowMask;
76 if(style & wxRESIZE_BORDER)
77 styleMask |= NSResizableWindowMask;
78 if(style & wxSIMPLE_BORDER)
79 styleMask |= NSBorderlessWindowMask;
80 return styleMask;
81 }
82
83 bool wxTopLevelWindowCocoa::Create(wxWindow *parent,
84 wxWindowID winid,
85 const wxString& title,
86 const wxPoint& pos,
87 const wxSize& size,
88 long style,
89 const wxString& name)
90 {
91 wxAutoNSAutoreleasePool pool;
92 wxTopLevelWindows.Append(this);
93
94 if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name))
95 return FALSE;
96
97 if ( parent )
98 parent->AddChild(this);
99
100 unsigned int cocoaStyle = NSWindowStyleForWxStyle(style);
101 if(style & wxFRAME_TOOL_WINDOW)
102 cocoaStyle |= NSUtilityWindowMask;
103
104 // NOTE: y-origin needs to be flipped.
105 NSRect cocoaRect = [NSWindow contentRectForFrameRect:NSMakeRect(pos.x,pos.y,size.x,size.y) styleMask:cocoaStyle];
106
107 m_cocoaNSWindow = NULL;
108 m_cocoaNSView = NULL;
109 if(style & wxFRAME_TOOL_WINDOW)
110 SetNSWindow([[NSPanel alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
111 else
112 SetNSWindow([[NSWindow alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
113 // NOTE: SetNSWindow has retained the Cocoa object for this object.
114 // Because we do not release on close, the following release matches the
115 // above alloc and thus the retain count will be 1.
116 [m_cocoaNSWindow release];
117
118 if(style & wxFRAME_NO_TASKBAR)
119 [m_cocoaNSWindow setExcludedFromWindowsMenu: YES];
120 if(style & wxSTAY_ON_TOP)
121 [m_cocoaNSWindow setLevel:NSFloatingWindowLevel];
122 [m_cocoaNSWindow setTitle:wxNSStringWithWxString(title)];
123 return TRUE;
124 }
125
126 wxTopLevelWindowCocoa::~wxTopLevelWindowCocoa()
127 {
128 wxAutoNSAutoreleasePool pool;
129 DestroyChildren();
130 SetNSWindow(NULL);
131 }
132
133 // ----------------------------------------------------------------------------
134 // wxTopLevelWindowCocoa Cocoa Specifics
135 // ----------------------------------------------------------------------------
136
137 wxMenuBar* wxTopLevelWindowCocoa::GetAppMenuBar()
138 {
139 wxTopLevelWindowCocoa *parent = wxDynamicCast(GetParent(),wxTopLevelWindow);
140 if(parent)
141 return parent->GetAppMenuBar();
142 return NULL;
143 }
144
145 void wxTopLevelWindowCocoa::SetNSWindow(WX_NSWindow cocoaNSWindow)
146 {
147 bool need_debug = cocoaNSWindow || m_cocoaNSWindow;
148 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [m_cocoaNSWindow=%p retainCount]=%d",this,m_cocoaNSWindow,[m_cocoaNSWindow retainCount]);
149 DisassociateNSWindow(m_cocoaNSWindow);
150 [cocoaNSWindow retain];
151 [m_cocoaNSWindow release];
152 m_cocoaNSWindow = cocoaNSWindow;
153 if(m_cocoaNSWindow)
154 SetNSView([m_cocoaNSWindow contentView]);
155 else
156 SetNSView(NULL);
157 AssociateNSWindow(m_cocoaNSWindow);
158 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [cocoaNSWindow=%p retainCount]=%d",this,cocoaNSWindow,[cocoaNSWindow retainCount]);
159 }
160
161 void wxTopLevelWindowCocoa::CocoaReplaceView(WX_NSView oldView, WX_NSView newView)
162 {
163 if([m_cocoaNSWindow contentView] == (id)oldView)
164 [m_cocoaNSWindow setContentView:newView];
165 }
166
167 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeKey(void)
168 {
169 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeKey",this);
170 wxMenuBarManager::GetInstance()->WindowDidBecomeKey(this);
171 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
172 event.SetEventObject(this);
173 GetEventHandler()->ProcessEvent(event);
174 }
175
176 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignKey(void)
177 {
178 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignKey",this);
179 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
180 event.SetEventObject(this);
181 GetEventHandler()->ProcessEvent(event);
182 wxMenuBarManager::GetInstance()->WindowDidResignKey(this);
183 }
184
185 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeMain(void)
186 {
187 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeMain",this);
188 wxMenuBarManager::GetInstance()->WindowDidBecomeMain(this);
189 }
190
191 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignMain(void)
192 {
193 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignMain",this);
194 wxMenuBarManager::GetInstance()->WindowDidResignMain(this);
195 }
196
197 void wxTopLevelWindowCocoa::CocoaDelegate_windowWillClose(void)
198 {
199 m_closed = true;
200 Destroy();
201 /* Be SURE that idle events get ran. If the window was not active when
202 it was closed, then there will be no more events to trigger this and
203 therefore it must be done here */
204 wxTheApp->CocoaInstallRequestedIdleHandler();
205 }
206
207 bool wxTopLevelWindowCocoa::CocoaDelegate_windowShouldClose()
208 {
209 return wxWindowBase::Close(false);
210 }
211
212 // ----------------------------------------------------------------------------
213 // wxTopLevelWindowCocoa maximize/minimize
214 // ----------------------------------------------------------------------------
215
216 void wxTopLevelWindowCocoa::Maximize(bool maximize)
217 {
218 }
219
220 bool wxTopLevelWindowCocoa::IsMaximized() const
221 {
222 return false ;
223 }
224
225 void wxTopLevelWindowCocoa::Iconize(bool iconize)
226 {
227 }
228
229 bool wxTopLevelWindowCocoa::IsIconized() const
230 {
231 return FALSE;
232 }
233
234 void wxTopLevelWindowCocoa::Restore()
235 {
236 }
237
238 bool wxTopLevelWindowCocoa::Show(bool show)
239 {
240 if(m_isShown == show)
241 return false;
242 wxAutoNSAutoreleasePool pool;
243 if(show)
244 {
245 // Send the window a size event because wxWindows apps expect it
246 // NOTE: This should really only be done the first time a window
247 // is shown. I doubt this will cause any problems though.
248 wxSizeEvent event(GetSize(), GetId());
249 event.SetEventObject(this);
250 GetEventHandler()->ProcessEvent(event);
251
252 [m_cocoaNSWindow makeKeyAndOrderFront:m_cocoaNSWindow];
253 }
254 else
255 [m_cocoaNSWindow orderOut:m_cocoaNSWindow];
256 m_isShown = show;
257 return true;
258 }
259
260 bool wxTopLevelWindowCocoa::Close(bool force)
261 {
262 if(force)
263 return wxWindowBase::Close(force);
264 // performClose will fake the user clicking the close button which
265 // will invoke windowShouldClose which will call the base class version
266 // of Close() which will NOT Destroy() the window (see below) but
267 // if closing is not stopped, then performClose will go ahead and
268 // close the window which will send the close notifications setting
269 // m_closed to true and Destroy()ing the window.
270 [m_cocoaNSWindow performClose:m_cocoaNSWindow];
271 return m_closed;
272 }
273
274 void wxTopLevelWindowCocoa::OnCloseWindow(wxCloseEvent& event)
275 {
276 // If the event was forced, close the window which will Destroy() it
277 if(!event.CanVeto())
278 [m_cocoaNSWindow close];
279 // if the event was not forced, it's probably because the user clicked
280 // the close button, or Close(false) was called which (see above) is
281 // redirected to performClose and thus Cocoa itself will close the window
282 }
283
284 // ----------------------------------------------------------------------------
285 // wxTopLevelWindowCocoa misc
286 // ----------------------------------------------------------------------------
287
288 bool wxTopLevelWindowCocoa::ShowFullScreen(bool show, long style)
289 {
290 return FALSE;
291 }
292
293 bool wxTopLevelWindowCocoa::IsFullScreen() const
294 {
295 return FALSE;
296 }
297
298 void wxTopLevelWindowCocoa::CocoaSetWxWindowSize(int width, int height)
299 {
300 // Set the NSView size by setting the frame size to enclose it
301 unsigned int styleMask = [m_cocoaNSWindow styleMask];
302 NSRect frameRect = [m_cocoaNSWindow frame];
303 NSRect contentRect = [NSWindow
304 contentRectForFrameRect: frameRect
305 styleMask: styleMask];
306 contentRect.size.width = width;
307 contentRect.size.height = height;
308 frameRect = [NSWindow
309 frameRectForContentRect: contentRect
310 styleMask: styleMask];
311 [m_cocoaNSWindow setFrame: frameRect display: NO];
312 }
313
314 void wxTopLevelWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
315 {
316 // wxLogDebug("wxTopLevelWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
317
318 NSRect cocoaRect = NSMakeRect(x,y,width,height);
319 [m_cocoaNSWindow setFrame: cocoaRect display:NO];
320 }
321
322 void wxTopLevelWindowCocoa::DoGetSize(int *w, int *h) const
323 {
324 NSRect cocoaRect = [m_cocoaNSWindow frame];
325 if(w)
326 *w=(int)cocoaRect.size.width;
327 if(h)
328 *h=(int)cocoaRect.size.height;
329 // wxLogDebug("wxTopLevelWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
330 }
331
332 void wxTopLevelWindowCocoa::DoGetPosition(int *x, int *y) const
333 {
334 NSRect cocoaRect = [m_cocoaNSWindow frame];
335 if(x)
336 *x=(int)cocoaRect.origin.x;
337 if(y)
338 *y=(int)cocoaRect.origin.y;
339 // wxLogDebug("wxTopLevelWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);
340 }
341