Support precompiled headers
[wxWidgets.git] / src / cocoa / dialog.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/dialog.mm
3 // Purpose:     wxDialog class
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2002/12/15
7 // RCS-ID:      $Id: 
8 // Copyright:   2002 David Elliott
9 // Licence:     wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13 #ifndef WX_PRECOMP
14     #include "wx/log.h"
15     #include "wx/app.h"
16     #include "wx/dialog.h"
17     #include "wx/settings.h"
18 #endif //WX_PRECOMP
19
20 #include "wx/cocoa/autorelease.h"
21
22 #import <AppKit/NSPanel.h>
23 #import <AppKit/NSApplication.h>
24
25 // Lists to keep track of windows, so we can disable/enable them
26 // for modal dialogs
27 static wxWindowList wxModalDialogs;
28
29 IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow)
30
31 BEGIN_EVENT_TABLE(wxDialog, wxDialogBase)
32   EVT_BUTTON(wxID_OK, wxDialog::OnOK)
33   EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
34   EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
35   EVT_CLOSE(wxDialog::OnCloseWindow)
36 END_EVENT_TABLE()
37
38 WX_IMPLEMENT_COCOA_OWNER(wxDialog,NSPanel,NSWindow,NSWindow)
39
40 void wxDialog::Init()
41 {
42     SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
43 }
44
45 bool wxDialog::Create(wxWindow *parent, wxWindowID winid,
46            const wxString& title,
47            const wxPoint& pos,
48            const wxSize& size,
49            long style,
50            const wxString& name)
51 {
52     wxAutoNSAutoreleasePool pool;
53     wxTopLevelWindows.Append(this);
54
55     if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name))
56         return false;
57
58     if (parent)
59         parent->AddChild(this);
60
61     NSRect cocoaRect = NSMakeRect(300,300,200,200);
62
63     unsigned int cocoaStyle = 0;
64     cocoaStyle |= NSTitledWindowMask;
65     cocoaStyle |= NSClosableWindowMask;
66     cocoaStyle |= NSMiniaturizableWindowMask;
67     cocoaStyle |= NSResizableWindowMask;
68
69     m_cocoaNSWindow = NULL;
70     SetNSPanel([[NSPanel alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
71     // NOTE: SetNSWindow has retained the Cocoa object for this object.
72     // Because we do not release on close, the following release matches the
73     // above alloc and thus the retain count will be 1.
74     [m_cocoaNSWindow release];
75     wxLogDebug("wxDialog m_cocoaNSWindow retainCount=%d",[m_cocoaNSWindow retainCount]);
76
77     return true;
78 }
79
80 wxDialog::~wxDialog()
81 {
82     wxLogDebug("Destroying");
83     // setReleasedWhenClosed: NO
84     [m_cocoaNSWindow close];
85     DisassociateNSPanel(m_cocoaNSWindow);
86 }
87
88 void wxDialog::Cocoa_close(void)
89 {
90     m_closed = true;
91     /* Actually, this isn't true anymore */
92     wxLogDebug("Woah: Dialogs are not generally closed");
93 }
94
95 void wxDialog::SetModal(bool flag)
96 {
97     if ( flag )
98     {
99         wxModelessWindows.DeleteObject(this);
100         m_windowStyle |= wxDIALOG_MODAL ;
101     }
102     else
103     {
104         m_windowStyle &= ~wxDIALOG_MODAL ;
105         wxModelessWindows.Append(this);
106     }
107 }
108
109 bool wxDialog::Show(bool show)
110 {
111     if(m_isShown == show)
112         return false;
113     if(show)
114         InitDialog();
115     if(IsModal())
116     {
117         m_isShown = show;
118         if(show)
119         {
120             wxAutoNSAutoreleasePool pool;
121             wxModalDialogs.Append(this);
122             wxLogDebug("runModal");
123             [wxTheApp->GetNSApplication() runModalForWindow:m_cocoaNSWindow];
124             wxLogDebug("runModal END");
125         }
126         else
127         {
128             wxLogDebug("abortModal");
129             [wxTheApp->GetNSApplication() abortModal];
130             wxModalDialogs.DeleteObject(this);
131         }
132     }
133     else
134         return wxTopLevelWindow::Show(show);
135     return true;
136 }
137
138 // Replacement for Show(TRUE) for modal dialogs - returns return code
139 int wxDialog::ShowModal()
140 {
141     if(!IsModal())
142         SetModal(true);
143     Show(true);
144     return GetReturnCode();
145 }
146
147 // EndModal will work for any dialog
148 void wxDialog::EndModal(int retCode)
149 {
150     SetReturnCode(retCode);
151     Show(false);
152 }
153
154 bool wxDialog::IsModal() const
155 {
156     return (GetWindowStyleFlag() & wxDIALOG_MODAL);
157 }
158
159 void wxDialog::OnCloseWindow(wxCloseEvent& event)
160 {
161     // We'll send a Cancel message by default,
162     // which may close the dialog.
163     // Check for looping if the Cancel event handler calls Close().
164
165     // Note that if a cancel button and handler aren't present in the dialog,
166     // nothing will happen when you close the dialog via the window manager, or
167     // via Close().
168     // We wouldn't want to destroy the dialog by default, since the dialog may have been
169     // created on the stack.
170     // However, this does mean that calling dialog->Close() won't delete the dialog
171     // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
172     // sure to destroy the dialog.
173     // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
174     // ALWAYS VETO THIS EVENT!!!!
175     event.Veto();
176
177     static wxList closing;
178     
179     if ( closing.Member(this) )
180     {
181         wxLogDebug("WARNING: Attempting to recursively call Close for dialog");
182         return;
183     }
184     
185     closing.Append(this);
186     
187     wxLogDebug("Sending Cancel Event");
188     wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
189     cancelEvent.SetEventObject( this );
190     GetEventHandler()->ProcessEvent(cancelEvent); // This may close the dialog
191
192     closing.DeleteObject(this);
193 }
194
195 // Standard buttons
196 void wxDialog::OnOK(wxCommandEvent& event)
197 {
198     if ( Validate() && TransferDataFromWindow() )
199     {
200         EndModal(wxID_OK);
201     }
202 }
203
204 void wxDialog::OnApply(wxCommandEvent& event)
205 {
206         if (Validate())
207                 TransferDataFromWindow();
208         // TODO probably need to disable the Apply button until things change again
209 }
210
211 void wxDialog::OnCancel(wxCommandEvent& event)
212 {
213     wxLogDebug("Cancelled!");
214     EndModal(wxID_CANCEL);
215 }
216