Don't pass notifications to wxMenuBarManager. It will be getting its own.
[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     wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
171     event.SetEventObject(this);
172     GetEventHandler()->ProcessEvent(event);
173 }
174
175 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignKey(void)
176 {
177     wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignKey",this);
178     wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
179     event.SetEventObject(this);
180     GetEventHandler()->ProcessEvent(event);
181 }
182
183 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeMain(void)
184 {
185     wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeMain",this);
186 }
187
188 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignMain(void)
189 {
190     wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignMain",this);
191 }
192
193 void wxTopLevelWindowCocoa::CocoaDelegate_windowWillClose(void)
194 {
195     m_closed = true;
196     Destroy();
197     /* Be SURE that idle events get ran.  If the window was not active when
198     it was closed, then there will be no more events to trigger this and
199     therefore it must be done here */
200     wxTheApp->CocoaInstallRequestedIdleHandler();
201 }
202
203 bool wxTopLevelWindowCocoa::CocoaDelegate_windowShouldClose()
204 {
205     return wxWindowBase::Close(false);
206 }
207
208 // ----------------------------------------------------------------------------
209 // wxTopLevelWindowCocoa maximize/minimize
210 // ----------------------------------------------------------------------------
211
212 void wxTopLevelWindowCocoa::Maximize(bool maximize)
213 {
214 }
215
216 bool wxTopLevelWindowCocoa::IsMaximized() const
217 {
218     return false ; 
219 }
220
221 void wxTopLevelWindowCocoa::Iconize(bool iconize)
222 {
223 }
224
225 bool wxTopLevelWindowCocoa::IsIconized() const
226 {
227     return FALSE;
228 }
229
230 void wxTopLevelWindowCocoa::Restore()
231 {
232 }
233
234 bool wxTopLevelWindowCocoa::Show(bool show)
235 {
236     if(m_isShown == show)
237         return false;
238     wxAutoNSAutoreleasePool pool;
239     if(show)
240     {
241         // Send the window a size event because wxWindows apps expect it
242         // NOTE: This should really only be done the first time a window
243         // is shown.  I doubt this will cause any problems though.
244         wxSizeEvent event(GetSize(), GetId());
245         event.SetEventObject(this);
246         GetEventHandler()->ProcessEvent(event);
247
248         [m_cocoaNSWindow makeKeyAndOrderFront:m_cocoaNSWindow];
249     }
250     else
251         [m_cocoaNSWindow orderOut:m_cocoaNSWindow];
252     m_isShown = show;
253     return true;
254 }
255
256 bool wxTopLevelWindowCocoa::Close(bool force)
257 {
258     if(force)
259         return wxWindowBase::Close(force);
260     // performClose  will fake the user clicking the close button which
261     // will invoke windowShouldClose which will call the base class version
262     // of Close() which will NOT Destroy() the window (see below) but
263     // if closing is not stopped, then performClose will go ahead and
264     // close the window which will send the close notifications setting
265     // m_closed to true and Destroy()ing the window.
266     [m_cocoaNSWindow performClose:m_cocoaNSWindow];
267     return m_closed;
268 }
269
270 void wxTopLevelWindowCocoa::OnCloseWindow(wxCloseEvent& event)
271 {
272     // If the event was forced, close the window which will Destroy() it
273     if(!event.CanVeto())
274         [m_cocoaNSWindow close];
275     // if the event was not forced, it's probably because the user clicked
276     // the close button, or Close(false) was called which (see above) is
277     // redirected to performClose and thus Cocoa itself will close the window
278 }
279
280 // ----------------------------------------------------------------------------
281 // wxTopLevelWindowCocoa misc
282 // ----------------------------------------------------------------------------
283
284 bool wxTopLevelWindowCocoa::ShowFullScreen(bool show, long style)
285 {
286     return FALSE;
287 }
288
289 bool wxTopLevelWindowCocoa::IsFullScreen() const
290 {
291     return FALSE;
292 }
293
294 void wxTopLevelWindowCocoa::CocoaSetWxWindowSize(int width, int height)
295 {
296     // Set the NSView size by setting the frame size to enclose it
297     unsigned int styleMask = [m_cocoaNSWindow styleMask];
298     NSRect frameRect = [m_cocoaNSWindow frame];
299     NSRect contentRect = [NSWindow
300         contentRectForFrameRect: frameRect
301         styleMask: styleMask];
302     contentRect.size.width = width;
303     contentRect.size.height = height;
304     frameRect = [NSWindow
305         frameRectForContentRect: contentRect
306         styleMask: styleMask];
307     [m_cocoaNSWindow setFrame: frameRect display: NO];
308 }
309
310 void wxTopLevelWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
311 {
312 //    wxLogDebug("wxTopLevelWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
313
314     NSRect cocoaRect = NSMakeRect(x,y,width,height);
315     [m_cocoaNSWindow setFrame: cocoaRect display:NO];
316 }
317
318 void wxTopLevelWindowCocoa::DoGetSize(int *w, int *h) const
319 {
320     NSRect cocoaRect = [m_cocoaNSWindow frame];
321     if(w)
322         *w=(int)cocoaRect.size.width;
323     if(h)
324         *h=(int)cocoaRect.size.height;
325 //    wxLogDebug("wxTopLevelWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
326 }
327
328 void wxTopLevelWindowCocoa::DoGetPosition(int *x, int *y) const
329 {
330     NSRect cocoaRect = [m_cocoaNSWindow frame];
331     if(x)
332         *x=(int)cocoaRect.origin.x;
333     if(y)
334         *y=(int)cocoaRect.origin.y;
335 //    wxLogDebug("wxTopLevelWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);
336 }
337