CodeWarrior Obj-C++ requires explicit casts from id to Objective-C types
[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] == (id)oldView)
128         [m_cocoaNSWindow setContentView:newView];
129 }
130
131 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeKey(void)
132 {
133     wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeKey",this);
134     wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
135     event.SetEventObject(this);
136     GetEventHandler()->ProcessEvent(event);
137 }
138
139 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignKey(void)
140 {
141     wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignKey",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::CocoaDelegate_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     if(m_isShown == show)
191         return false;
192     wxAutoNSAutoreleasePool pool;
193     if(show)
194     {
195         // Send the window a size event because wxWindows apps expect it
196         // NOTE: This should really only be done the first time a window
197         // is shown.  I doubt this will cause any problems though.
198         wxSizeEvent event(GetSize(), GetId());
199         event.SetEventObject(this);
200         GetEventHandler()->ProcessEvent(event);
201
202         [m_cocoaNSWindow makeKeyAndOrderFront:m_cocoaNSWindow];
203     }
204     else
205         [m_cocoaNSWindow orderOut:m_cocoaNSWindow];
206     m_isShown = show;
207     return true;
208 }
209
210 bool wxTopLevelWindowCocoa::Close(bool force)
211 {
212     if(force)
213         return wxWindowBase::Close(force);
214     // performClose  will fake the user clicking the close button which
215     // will invoke windowShouldClose which will call the base class version
216     // of Close() which will NOT Destroy() the window (see below) but
217     // if closing is not stopped, then performClose will go ahead and
218     // close the window which will invoke Cocoa_close() setting m_closed
219     // to true and Destroy()ing the window.
220     [m_cocoaNSWindow performClose:m_cocoaNSWindow];
221     return m_closed;
222 }
223
224 void wxTopLevelWindowCocoa::OnCloseWindow(wxCloseEvent& event)
225 {
226     // If the event was forced, close the window which will Destroy() it
227     if(!event.CanVeto())
228         [m_cocoaNSWindow close];
229     // if the event was not forced, it's probably because the user clicked
230     // the close button, or Close(false) was called which (see above) is
231     // redirected to performClose and thus Cocoa itself will close the window
232 }
233
234 // ----------------------------------------------------------------------------
235 // wxTopLevelWindowCocoa misc
236 // ----------------------------------------------------------------------------
237
238 bool wxTopLevelWindowCocoa::ShowFullScreen(bool show, long style)
239 {
240     return FALSE;
241 }
242
243 bool wxTopLevelWindowCocoa::IsFullScreen() const
244 {
245     return FALSE;
246 }
247
248 void wxTopLevelWindowCocoa::CocoaSetWxWindowSize(int width, int height)
249 {
250     // Set the NSView size by setting the frame size to enclose it
251     unsigned int styleMask = [m_cocoaNSWindow styleMask];
252     NSRect frameRect = [m_cocoaNSWindow frame];
253     NSRect contentRect = [NSWindow
254         contentRectForFrameRect: frameRect
255         styleMask: styleMask];
256     contentRect.size.width = width;
257     contentRect.size.height = height;
258     frameRect = [NSWindow
259         frameRectForContentRect: contentRect
260         styleMask: styleMask];
261     [m_cocoaNSWindow setFrame: frameRect display: NO];
262 }
263
264 void wxTopLevelWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
265 {
266 //    wxLogDebug("wxTopLevelWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
267
268     NSRect cocoaRect = NSMakeRect(x,y,width,height);
269     [m_cocoaNSWindow setFrame: cocoaRect display:NO];
270 }
271
272 void wxTopLevelWindowCocoa::DoGetSize(int *w, int *h) const
273 {
274     NSRect cocoaRect = [m_cocoaNSWindow frame];
275     if(w)
276         *w=(int)cocoaRect.size.width;
277     if(h)
278         *h=(int)cocoaRect.size.height;
279 //    wxLogDebug("wxTopLevelWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
280 }
281
282 void wxTopLevelWindowCocoa::DoGetPosition(int *x, int *y) const
283 {
284     NSRect cocoaRect = [m_cocoaNSWindow frame];
285     if(x)
286         *x=(int)cocoaRect.origin.x;
287     if(y)
288         *y=(int)cocoaRect.origin.y;
289 //    wxLogDebug("wxTopLevelWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);
290 }
291