]>
Commit | Line | Data |
---|---|---|
fb896a32 DE |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: src/cocoa/dialog.mm | |
3 | // Purpose: wxDialog class | |
4 | // Author: David Elliott | |
5 | // Modified by: | |
6 | // Created: 2002/12/15 | |
ec157c8f | 7 | // RCS-ID: $Id: |
fb896a32 | 8 | // Copyright: 2002 David Elliott |
ec157c8f | 9 | // Licence: wxWidgets licence |
fb896a32 DE |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
449c5673 | 12 | #include "wx/wxprec.h" |
fdf565fe WS |
13 | |
14 | #include "wx/dialog.h" | |
15 | ||
449c5673 DE |
16 | #ifndef WX_PRECOMP |
17 | #include "wx/log.h" | |
18 | #include "wx/app.h" | |
449c5673 DE |
19 | #include "wx/settings.h" |
20 | #endif //WX_PRECOMP | |
fb896a32 | 21 | |
7fc77f30 | 22 | #include "wx/cocoa/autorelease.h" |
35812955 | 23 | #include "wx/cocoa/string.h" |
7fc77f30 | 24 | |
fb896a32 DE |
25 | #import <AppKit/NSPanel.h> |
26 | #import <AppKit/NSApplication.h> | |
47885968 DE |
27 | #import <AppKit/NSEvent.h> |
28 | #import <Foundation/NSRunLoop.h> | |
fb896a32 DE |
29 | |
30 | // Lists to keep track of windows, so we can disable/enable them | |
31 | // for modal dialogs | |
32 | static wxWindowList wxModalDialogs; | |
33 | ||
34 | IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow) | |
35 | ||
36 | BEGIN_EVENT_TABLE(wxDialog, wxDialogBase) | |
fdf565fe WS |
37 | EVT_BUTTON(wxID_OK, wxDialog::OnOK) |
38 | EVT_BUTTON(wxID_APPLY, wxDialog::OnApply) | |
39 | EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel) | |
40 | EVT_CLOSE(wxDialog::OnCloseWindow) | |
fb896a32 DE |
41 | END_EVENT_TABLE() |
42 | ||
43 | WX_IMPLEMENT_COCOA_OWNER(wxDialog,NSPanel,NSWindow,NSWindow) | |
44 | ||
45 | void wxDialog::Init() | |
46 | { | |
90c10896 | 47 | m_isModal = false; |
ec157c8f | 48 | SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); |
fb896a32 DE |
49 | } |
50 | ||
51 | bool wxDialog::Create(wxWindow *parent, wxWindowID winid, | |
52 | const wxString& title, | |
53 | const wxPoint& pos, | |
54 | const wxSize& size, | |
55 | long style, | |
56 | const wxString& name) | |
57 | { | |
7fc77f30 | 58 | wxAutoNSAutoreleasePool pool; |
fb896a32 DE |
59 | wxTopLevelWindows.Append(this); |
60 | ||
61 | if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name)) | |
62 | return false; | |
63 | ||
64 | if (parent) | |
65 | parent->AddChild(this); | |
66 | ||
67 | NSRect cocoaRect = NSMakeRect(300,300,200,200); | |
68 | ||
69 | unsigned int cocoaStyle = 0; | |
70 | cocoaStyle |= NSTitledWindowMask; | |
71 | cocoaStyle |= NSClosableWindowMask; | |
72 | cocoaStyle |= NSMiniaturizableWindowMask; | |
73 | cocoaStyle |= NSResizableWindowMask; | |
74 | ||
75 | m_cocoaNSWindow = NULL; | |
76 | SetNSPanel([[NSPanel alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]); | |
77 | // NOTE: SetNSWindow has retained the Cocoa object for this object. | |
78 | // Because we do not release on close, the following release matches the | |
79 | // above alloc and thus the retain count will be 1. | |
80 | [m_cocoaNSWindow release]; | |
48580976 | 81 | wxLogTrace(wxTRACE_COCOA_RetainRelease,wxT("wxDialog m_cocoaNSWindow retainCount=%d"),[m_cocoaNSWindow retainCount]); |
35812955 DE |
82 | [m_cocoaNSWindow setTitle:wxNSStringWithWxString(title)]; |
83 | [m_cocoaNSWindow setHidesOnDeactivate:NO]; | |
fb896a32 DE |
84 | |
85 | return true; | |
86 | } | |
87 | ||
88 | wxDialog::~wxDialog() | |
89 | { | |
162c4aad | 90 | DisassociateNSPanel(GetNSPanel()); |
fb896a32 DE |
91 | } |
92 | ||
9692f42b | 93 | void wxDialog::CocoaDelegate_windowWillClose(void) |
fb896a32 DE |
94 | { |
95 | m_closed = true; | |
96 | /* Actually, this isn't true anymore */ | |
48580976 | 97 | wxLogTrace(wxTRACE_COCOA,wxT("Woah: Dialogs are not generally closed")); |
fb896a32 DE |
98 | } |
99 | ||
100 | void wxDialog::SetModal(bool flag) | |
101 | { | |
90c10896 | 102 | wxFAIL_MSG( wxT("wxDialog:SetModal obsolete now") ); |
fb896a32 DE |
103 | } |
104 | ||
105 | bool wxDialog::Show(bool show) | |
106 | { | |
0411b864 DE |
107 | if(m_isShown == show) |
108 | return false; | |
90c10896 | 109 | |
fb896a32 | 110 | if(show) |
fb896a32 | 111 | { |
90c10896 DE |
112 | wxAutoNSAutoreleasePool pool; |
113 | InitDialog(); | |
114 | if(IsModal()) | |
115 | { // ShowModal() will show the dialog | |
116 | m_isShown = true; | |
117 | return true; | |
fb896a32 | 118 | } |
90c10896 DE |
119 | } |
120 | else | |
121 | { | |
122 | if(IsModal()) | |
123 | { // this doesn't hide the dialog, base class Show(false) does. | |
48580976 | 124 | wxLogTrace(wxTRACE_COCOA,wxT("abortModal")); |
fb896a32 DE |
125 | [wxTheApp->GetNSApplication() abortModal]; |
126 | wxModalDialogs.DeleteObject(this); | |
90c10896 | 127 | m_isModal = false; |
fb896a32 DE |
128 | } |
129 | } | |
90c10896 | 130 | return wxTopLevelWindow::Show(show); |
fb896a32 DE |
131 | } |
132 | ||
90c10896 DE |
133 | // Shows the dialog and begins a modal event loop. When the event loop |
134 | // is stopped (via EndModal()) it returns the exit code. | |
fb896a32 DE |
135 | int wxDialog::ShowModal() |
136 | { | |
90c10896 DE |
137 | wxCHECK_MSG(!IsModal(),GetReturnCode(),wxT("wxDialog::ShowModal called within its own modal loop")); |
138 | ||
139 | // Show(true) will set m_isShown = true | |
140 | m_isShown = false; | |
141 | m_isModal = true; | |
142 | wxModalDialogs.Append(this); | |
143 | ||
144 | wxLogTrace(wxTRACE_COCOA,wxT("runModal")); | |
145 | NSApplication *theNSApp = wxTheApp->GetNSApplication(); | |
146 | // If the app hasn't started, flush the event queue | |
147 | // If we don't do this, the Dock doesn't get the message that | |
148 | // the app has started so will refuse to activate it. | |
149 | if(![theNSApp isRunning]) | |
150 | { | |
151 | // We should only do a few iterations so one pool should be okay | |
152 | wxAutoNSAutoreleasePool pool; | |
153 | while(NSEvent *event = [theNSApp | |
154 | nextEventMatchingMask:NSAnyEventMask | |
155 | untilDate:[NSDate distantPast] | |
156 | inMode:NSDefaultRunLoopMode | |
157 | dequeue: YES]) | |
158 | { | |
159 | [theNSApp sendEvent: event]; | |
160 | } | |
161 | } | |
162 | ||
fb896a32 | 163 | Show(true); |
90c10896 DE |
164 | do { |
165 | wxAutoNSAutoreleasePool pool; | |
166 | [wxTheApp->GetNSApplication() runModalForWindow:m_cocoaNSWindow]; | |
167 | } while(0); | |
168 | wxLogTrace(wxTRACE_COCOA,wxT("runModal END")); | |
169 | ||
fb896a32 DE |
170 | return GetReturnCode(); |
171 | } | |
172 | ||
fb896a32 DE |
173 | void wxDialog::EndModal(int retCode) |
174 | { | |
32794053 | 175 | wxASSERT_MSG(IsModal(), wxT("EndModal() should only be used within ShowModal()")); |
fb896a32 DE |
176 | SetReturnCode(retCode); |
177 | Show(false); | |
178 | } | |
179 | ||
acb96ac2 DE |
180 | void wxDialog::EndDialog(int retCode) |
181 | { | |
182 | if(IsModal()) | |
183 | EndModal(retCode); | |
184 | else | |
185 | Show(false); | |
186 | } | |
187 | ||
fb896a32 DE |
188 | void wxDialog::OnCloseWindow(wxCloseEvent& event) |
189 | { | |
190 | // We'll send a Cancel message by default, | |
191 | // which may close the dialog. | |
192 | // Check for looping if the Cancel event handler calls Close(). | |
193 | ||
194 | // Note that if a cancel button and handler aren't present in the dialog, | |
195 | // nothing will happen when you close the dialog via the window manager, or | |
196 | // via Close(). | |
197 | // We wouldn't want to destroy the dialog by default, since the dialog may have been | |
198 | // created on the stack. | |
199 | // However, this does mean that calling dialog->Close() won't delete the dialog | |
200 | // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be | |
201 | // sure to destroy the dialog. | |
202 | // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog. | |
203 | // ALWAYS VETO THIS EVENT!!!! | |
204 | event.Veto(); | |
205 | ||
206 | static wxList closing; | |
ec157c8f | 207 | |
fb896a32 DE |
208 | if ( closing.Member(this) ) |
209 | { | |
2b030203 | 210 | wxLogDebug(wxT("WARNING: Attempting to recursively call Close for dialog")); |
fb896a32 DE |
211 | return; |
212 | } | |
ec157c8f | 213 | |
fb896a32 | 214 | closing.Append(this); |
ec157c8f | 215 | |
48580976 | 216 | wxLogTrace(wxTRACE_COCOA,wxT("Sending Cancel Event")); |
fb896a32 DE |
217 | wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL); |
218 | cancelEvent.SetEventObject( this ); | |
219 | GetEventHandler()->ProcessEvent(cancelEvent); // This may close the dialog | |
220 | ||
221 | closing.DeleteObject(this); | |
222 | } | |
223 | ||
224 | // Standard buttons | |
225 | void wxDialog::OnOK(wxCommandEvent& event) | |
226 | { | |
227 | if ( Validate() && TransferDataFromWindow() ) | |
228 | { | |
acb96ac2 | 229 | EndDialog(wxID_OK); |
fb896a32 DE |
230 | } |
231 | } | |
232 | ||
233 | void wxDialog::OnApply(wxCommandEvent& event) | |
234 | { | |
ec157c8f WS |
235 | if (Validate()) |
236 | TransferDataFromWindow(); | |
237 | // TODO probably need to disable the Apply button until things change again | |
fb896a32 DE |
238 | } |
239 | ||
240 | void wxDialog::OnCancel(wxCommandEvent& event) | |
241 | { | |
48580976 | 242 | wxLogTrace(wxTRACE_COCOA,wxT("Cancelled!")); |
acb96ac2 | 243 | EndDialog(wxID_CANCEL); |
fb896a32 | 244 | } |