In destructor: DestroyChildren() and make sure m_cocoaNSView is NULL so that
[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::Cocoa_wxMenuItemAction(wxMenuItem& item)
126 {
127 }
128
129 void wxTopLevelWindowCocoa::Cocoa_close(void)
130 {
131     m_closed = true;
132     Destroy();
133     /* Be SURE that idle events get ran.  If the window was not active when
134     it was closed, then there will be no more events to trigger this and
135     therefore it must be done here */
136     wxTheApp->CocoaInstallRequestedIdleHandler();
137 }
138
139 bool wxTopLevelWindowCocoa::Cocoa_windowShouldClose()
140 {
141     return wxWindowBase::Close(false);
142 }
143
144 // ----------------------------------------------------------------------------
145 // wxTopLevelWindowCocoa maximize/minimize
146 // ----------------------------------------------------------------------------
147
148 void wxTopLevelWindowCocoa::Maximize(bool maximize)
149 {
150 }
151
152 bool wxTopLevelWindowCocoa::IsMaximized() const
153 {
154     return false ; 
155 }
156
157 void wxTopLevelWindowCocoa::Iconize(bool iconize)
158 {
159 }
160
161 bool wxTopLevelWindowCocoa::IsIconized() const
162 {
163     return FALSE;
164 }
165
166 void wxTopLevelWindowCocoa::Restore()
167 {
168 }
169
170 bool wxTopLevelWindowCocoa::Show(bool show)
171 {
172     wxAutoNSAutoreleasePool pool;
173     if(show)
174         [m_cocoaNSWindow makeKeyAndOrderFront:m_cocoaNSWindow];
175     else
176         [m_cocoaNSWindow orderOut:m_cocoaNSWindow];
177     return true;
178 }
179
180 bool wxTopLevelWindowCocoa::Close(bool force)
181 {
182     if(force)
183         return wxWindowBase::Close(force);
184     // performClose  will fake the user clicking the close button which
185     // will invoke windowShouldClose which will call the base class version
186     // of Close() which will NOT Destroy() the window (see below) but
187     // if closing is not stopped, then performClose will go ahead and
188     // close the window which will invoke Cocoa_close() setting m_closed
189     // to true and Destroy()ing the window.
190     [m_cocoaNSWindow performClose:m_cocoaNSWindow];
191     return m_closed;
192 }
193
194 void wxTopLevelWindowCocoa::OnCloseWindow(wxCloseEvent& event)
195 {
196     // If the event was forced, close the window which will Destroy() it
197     if(!event.CanVeto())
198         [m_cocoaNSWindow close];
199     // if the event was not forced, it's probably because the user clicked
200     // the close button, or Close(false) was called which (see above) is
201     // redirected to performClose and thus Cocoa itself will close the window
202 }
203
204 // ----------------------------------------------------------------------------
205 // wxTopLevelWindowCocoa misc
206 // ----------------------------------------------------------------------------
207
208 bool wxTopLevelWindowCocoa::ShowFullScreen(bool show, long style)
209 {
210     return FALSE;
211 }
212
213 bool wxTopLevelWindowCocoa::IsFullScreen() const
214 {
215     return FALSE;
216 }
217
218 void wxTopLevelWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
219 {
220     wxLogDebug("wxTopLevelWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
221
222     NSRect cocoaRect = NSMakeRect(x,y,width,height);
223     [m_cocoaNSWindow setFrame: cocoaRect display:NO];
224 }
225
226 void wxTopLevelWindowCocoa::DoGetSize(int *w, int *h) const
227 {
228     NSRect cocoaRect = [m_cocoaNSWindow frame];
229     if(w)
230         *w=(int)cocoaRect.size.width;
231     if(h)
232         *h=(int)cocoaRect.size.height;
233     wxLogDebug("wxTopLevelWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
234 }
235
236 void wxTopLevelWindowCocoa::DoGetPosition(int *x, int *y) const
237 {
238     NSRect cocoaRect = [m_cocoaNSWindow frame];
239     if(x)
240         *x=(int)cocoaRect.origin.x;
241     if(y)
242         *y=(int)cocoaRect.origin.y;
243     wxLogDebug("wxTopLevelWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);
244 }
245