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