* Added virtual GetAppMenuBar() which returns the app-wide menubar which
[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/mbarman.h"
33
34 #import <AppKit/NSView.h>
35 #import <AppKit/NSWindow.h>
36 // ----------------------------------------------------------------------------
37 // globals
38 // ----------------------------------------------------------------------------
39
40 // list of all frames and modeless dialogs
41 wxWindowList       wxModelessWindows;
42
43 // ============================================================================
44 // wxTopLevelWindowCocoa implementation
45 // ============================================================================
46
47 // ----------------------------------------------------------------------------
48 // wxTopLevelWindowCocoa creation
49 // ----------------------------------------------------------------------------
50 BEGIN_EVENT_TABLE(wxTopLevelWindowCocoa,wxTopLevelWindowBase)
51     EVT_CLOSE(wxTopLevelWindowCocoa::OnCloseWindow)
52 END_EVENT_TABLE()
53
54 void wxTopLevelWindowCocoa::Init()
55 {
56     m_iconized =
57     m_maximizeOnShow =
58     m_closed = false;
59 }
60
61 bool wxTopLevelWindowCocoa::Create(wxWindow *parent,
62                                  wxWindowID winid,
63                                  const wxString& title,
64                                  const wxPoint& pos,
65                                  const wxSize& size,
66                                  long style,
67                                  const wxString& name)
68 {
69     wxAutoNSAutoreleasePool pool;
70     wxTopLevelWindows.Append(this);
71
72     if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name))
73         return FALSE;
74
75     if ( parent )
76         parent->AddChild(this);
77
78     // TODO: get rect from given position/size
79     NSRect cocoaRect =  NSMakeRect(100,100,200,200);
80
81     // TODO: Set flags given wxWindows style
82     unsigned int cocoaStyle = 0;
83     cocoaStyle |= NSTitledWindowMask;
84     cocoaStyle |= NSClosableWindowMask;
85     cocoaStyle |= NSMiniaturizableWindowMask;
86     cocoaStyle |= NSResizableWindowMask;
87
88     m_cocoaNSWindow = NULL;
89     m_cocoaNSView = NULL;
90     SetNSWindow([[NSWindow alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
91     // NOTE: SetNSWindow has retained the Cocoa object for this object.
92     // Because we do not release on close, the following release matches the
93     // above alloc and thus the retain count will be 1.
94     [m_cocoaNSWindow release];
95
96     return TRUE;
97 }
98
99 wxTopLevelWindowCocoa::~wxTopLevelWindowCocoa()
100 {
101     wxAutoNSAutoreleasePool pool;
102     DestroyChildren();
103     SetNSWindow(NULL);
104 }
105
106 // ----------------------------------------------------------------------------
107 // wxTopLevelWindowCocoa Cocoa Specifics
108 // ----------------------------------------------------------------------------
109
110 void wxTopLevelWindowCocoa::SetNSWindow(WX_NSWindow cocoaNSWindow)
111 {
112     bool need_debug = cocoaNSWindow || m_cocoaNSWindow;
113     if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [m_cocoaNSWindow=%p retainCount]=%d",this,m_cocoaNSWindow,[m_cocoaNSWindow retainCount]);
114     DisassociateNSWindow(m_cocoaNSWindow);
115     [cocoaNSWindow retain];
116     [m_cocoaNSWindow release];
117     m_cocoaNSWindow = cocoaNSWindow;
118     if(m_cocoaNSWindow)
119         SetNSView([m_cocoaNSWindow contentView]);
120     else
121         SetNSView(NULL);
122     AssociateNSWindow(m_cocoaNSWindow);
123     if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [cocoaNSWindow=%p retainCount]=%d",this,cocoaNSWindow,[cocoaNSWindow retainCount]);
124 }
125
126 void wxTopLevelWindowCocoa::CocoaReplaceView(WX_NSView oldView, WX_NSView newView)
127 {
128     if([m_cocoaNSWindow contentView] == (id)oldView)
129         [m_cocoaNSWindow setContentView:newView];
130 }
131
132 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeKey(void)
133 {
134     wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeKey",this);
135     wxMenuBarManager::GetInstance()->WindowDidBecomeKey(this);
136     wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
137     event.SetEventObject(this);
138     GetEventHandler()->ProcessEvent(event);
139 }
140
141 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignKey(void)
142 {
143     wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignKey",this);
144     wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
145     event.SetEventObject(this);
146     GetEventHandler()->ProcessEvent(event);
147     wxMenuBarManager::GetInstance()->WindowDidResignKey(this);
148 }
149
150 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeMain(void)
151 {
152     wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeMain",this);
153     wxMenuBarManager::GetInstance()->WindowDidBecomeMain(this);
154 }
155
156 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignMain(void)
157 {
158     wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignMain",this);
159     wxMenuBarManager::GetInstance()->WindowDidResignMain(this);
160 }
161
162 void wxTopLevelWindowCocoa::Cocoa_close(void)
163 {
164     m_closed = true;
165     Destroy();
166     /* Be SURE that idle events get ran.  If the window was not active when
167     it was closed, then there will be no more events to trigger this and
168     therefore it must be done here */
169     wxTheApp->CocoaInstallRequestedIdleHandler();
170 }
171
172 bool wxTopLevelWindowCocoa::CocoaDelegate_windowShouldClose()
173 {
174     return wxWindowBase::Close(false);
175 }
176
177 // ----------------------------------------------------------------------------
178 // wxTopLevelWindowCocoa maximize/minimize
179 // ----------------------------------------------------------------------------
180
181 void wxTopLevelWindowCocoa::Maximize(bool maximize)
182 {
183 }
184
185 bool wxTopLevelWindowCocoa::IsMaximized() const
186 {
187     return false ; 
188 }
189
190 void wxTopLevelWindowCocoa::Iconize(bool iconize)
191 {
192 }
193
194 bool wxTopLevelWindowCocoa::IsIconized() const
195 {
196     return FALSE;
197 }
198
199 void wxTopLevelWindowCocoa::Restore()
200 {
201 }
202
203 bool wxTopLevelWindowCocoa::Show(bool show)
204 {
205     if(m_isShown == show)
206         return false;
207     wxAutoNSAutoreleasePool pool;
208     if(show)
209     {
210         // Send the window a size event because wxWindows apps expect it
211         // NOTE: This should really only be done the first time a window
212         // is shown.  I doubt this will cause any problems though.
213         wxSizeEvent event(GetSize(), GetId());
214         event.SetEventObject(this);
215         GetEventHandler()->ProcessEvent(event);
216
217         [m_cocoaNSWindow makeKeyAndOrderFront:m_cocoaNSWindow];
218     }
219     else
220         [m_cocoaNSWindow orderOut:m_cocoaNSWindow];
221     m_isShown = show;
222     return true;
223 }
224
225 bool wxTopLevelWindowCocoa::Close(bool force)
226 {
227     if(force)
228         return wxWindowBase::Close(force);
229     // performClose  will fake the user clicking the close button which
230     // will invoke windowShouldClose which will call the base class version
231     // of Close() which will NOT Destroy() the window (see below) but
232     // if closing is not stopped, then performClose will go ahead and
233     // close the window which will invoke Cocoa_close() setting m_closed
234     // to true and Destroy()ing the window.
235     [m_cocoaNSWindow performClose:m_cocoaNSWindow];
236     return m_closed;
237 }
238
239 void wxTopLevelWindowCocoa::OnCloseWindow(wxCloseEvent& event)
240 {
241     // If the event was forced, close the window which will Destroy() it
242     if(!event.CanVeto())
243         [m_cocoaNSWindow close];
244     // if the event was not forced, it's probably because the user clicked
245     // the close button, or Close(false) was called which (see above) is
246     // redirected to performClose and thus Cocoa itself will close the window
247 }
248
249 // ----------------------------------------------------------------------------
250 // wxTopLevelWindowCocoa misc
251 // ----------------------------------------------------------------------------
252
253 bool wxTopLevelWindowCocoa::ShowFullScreen(bool show, long style)
254 {
255     return FALSE;
256 }
257
258 bool wxTopLevelWindowCocoa::IsFullScreen() const
259 {
260     return FALSE;
261 }
262
263 void wxTopLevelWindowCocoa::CocoaSetWxWindowSize(int width, int height)
264 {
265     // Set the NSView size by setting the frame size to enclose it
266     unsigned int styleMask = [m_cocoaNSWindow styleMask];
267     NSRect frameRect = [m_cocoaNSWindow frame];
268     NSRect contentRect = [NSWindow
269         contentRectForFrameRect: frameRect
270         styleMask: styleMask];
271     contentRect.size.width = width;
272     contentRect.size.height = height;
273     frameRect = [NSWindow
274         frameRectForContentRect: contentRect
275         styleMask: styleMask];
276     [m_cocoaNSWindow setFrame: frameRect display: NO];
277 }
278
279 void wxTopLevelWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
280 {
281 //    wxLogDebug("wxTopLevelWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
282
283     NSRect cocoaRect = NSMakeRect(x,y,width,height);
284     [m_cocoaNSWindow setFrame: cocoaRect display:NO];
285 }
286
287 void wxTopLevelWindowCocoa::DoGetSize(int *w, int *h) const
288 {
289     NSRect cocoaRect = [m_cocoaNSWindow frame];
290     if(w)
291         *w=(int)cocoaRect.size.width;
292     if(h)
293         *h=(int)cocoaRect.size.height;
294 //    wxLogDebug("wxTopLevelWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
295 }
296
297 void wxTopLevelWindowCocoa::DoGetPosition(int *x, int *y) const
298 {
299     NSRect cocoaRect = [m_cocoaNSWindow frame];
300     if(x)
301         *x=(int)cocoaRect.origin.x;
302     if(y)
303         *y=(int)cocoaRect.origin.y;
304 //    wxLogDebug("wxTopLevelWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);
305 }
306