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