Add wxTEST_DIALOG for testing of modal dialogs.
[wxWidgets.git] / src / cocoa / filedlg.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/filedlg.mm
3 // Purpose:     wxFileDialog for wxCocoa
4 // Author:      Ryan Norton
5 // Modified by:
6 // Created:     2004-10-02
7 // RCS-ID:      $Id$
8 // Copyright:   (c) Ryan Norton
9 // Licence:     wxWindows licence
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
23 #if wxUSE_FILEDLG
24
25 #include "wx/filedlg.h"
26
27 #ifndef WX_PRECOMP
28     #include "wx/msgdlg.h"
29     #include "wx/app.h"
30 #endif
31
32 #include "wx/filename.h"
33
34 #include "wx/cocoa/autorelease.h"
35 #include "wx/cocoa/string.h"
36 #include "wx/testing.h"
37
38 #import <AppKit/NSOpenPanel.h>
39 #import <AppKit/NSSavePanel.h>
40
41 #import <Foundation/NSArray.h>
42 // ============================================================================
43 // implementation
44 // ============================================================================
45
46 IMPLEMENT_CLASS(wxCocoaFileDialog, wxFileDialogBase)
47
48 // ----------------------------------------------------------------------------
49 // wxFileDialog
50 // ----------------------------------------------------------------------------
51
52 wxFileDialog::wxFileDialog(wxWindow *parent,
53                            const wxString& message,
54                            const wxString& defaultDir,
55                            const wxString& defaultFileName,
56                            const wxString& wildCard,
57                            long style,
58                            const wxPoint& pos,
59                            const wxSize& sz,
60                            const wxString& name)
61             : wxFileDialogBase(parent, message, defaultDir, defaultFileName,
62                                wildCard, style, pos, sz, name)
63 {
64     wxTopLevelWindows.Append(this);
65
66     wxASSERT(CreateBase(parent,wxID_ANY,pos,wxDefaultSize,style,wxDefaultValidator,wxDialogNameStr));
67
68     if ( parent )
69         parent->AddChild(this);
70
71     m_cocoaNSWindow = nil;
72     m_cocoaNSView = nil;
73
74     //Init the wildcard array
75     m_wildcards = [[NSMutableArray alloc] initWithCapacity:0];
76
77     //If the user requests to save - use a NSSavePanel
78     //else use a NSOpenPanel
79     if (HasFlag(wxFD_SAVE))
80     {
81         SetNSPanel([NSSavePanel savePanel]);
82
83         [GetNSSavePanel() setTitle:wxNSStringWithWxString(message)];
84
85         [GetNSSavePanel() setPrompt:@"Save"];
86         [GetNSSavePanel() setTreatsFilePackagesAsDirectories:YES];
87         [GetNSSavePanel() setCanSelectHiddenExtension:YES];
88
89 //        Cached as per-app in obj-c
90 //        [GetNSSavePanel() setExtensionHidden:YES];
91
92         //
93         // NB:  Note that only Panther supports wildcards
94         // with save dialogs - not that wildcards in save
95         // dialogs are all that useful, anyway :)
96         //
97     }
98     else //m_dialogStyle & wxFD_OPEN
99     {
100         SetNSPanel([NSOpenPanel openPanel]);
101         [m_cocoaNSWindow setTitle:wxNSStringWithWxString(message)];
102
103         [(NSOpenPanel*)m_cocoaNSWindow setAllowsMultipleSelection:(HasFlag(wxFD_MULTIPLE))];
104         [(NSOpenPanel*)m_cocoaNSWindow setResolvesAliases:YES];
105         [(NSOpenPanel*)m_cocoaNSWindow setCanChooseFiles:YES];
106         [(NSOpenPanel*)m_cocoaNSWindow setCanChooseDirectories:NO];
107         [GetNSSavePanel() setPrompt:@"Open"];
108
109         //convert wildcards - open panel only takes file extensions -
110         //no actual wildcards here :)
111         size_t lastwcpos = 0;
112         bool bDescription = true;
113         size_t i;
114         for(i = wildCard.find('|');
115                 i != wxString::npos;
116                 i = wildCard.find('|', lastwcpos+1))
117         {
118             size_t oldi = i;
119
120             if(!bDescription)
121             {
122                 bDescription = !bDescription;
123
124                 //work backwards looking for a period
125                 while(i != lastwcpos && wildCard[--i] != '.') {}
126
127                 if(i == lastwcpos)
128                 {
129                     //no extension - can't use this wildcard
130                     lastwcpos = oldi;
131                     continue;
132                 }
133
134                 [m_wildcards addObject:wxNSStringWithWxString(wildCard.substr(i+1, oldi-i-1))];
135             }
136             else
137                 bDescription = !bDescription;
138             lastwcpos = oldi;
139         }
140
141         if (!bDescription)
142         {
143             //get last wildcard
144             size_t oldi = wildCard.length();
145             i = oldi;
146
147             //work backwards looking for a period
148             while(i != lastwcpos && wildCard[--i] != '.') {}
149
150             if(i != lastwcpos)
151                 [m_wildcards addObject:wxNSStringWithWxString(wildCard.substr(i+1, oldi-i-1))];
152         }
153
154         if ([m_wildcards count] == 0)
155         {
156             [m_wildcards release];
157             m_wildcards = nil;
158         }
159     }
160 }
161
162 wxFileDialog::~wxFileDialog()
163 {
164     [m_wildcards release];
165 }
166
167 void wxFileDialog::GetPaths(wxArrayString& paths) const
168 {
169     paths.Empty();
170
171     wxString dir(m_dir);
172     if ( m_dir.Last() != wxT('\\') )
173         dir += wxT('\\');
174
175     size_t count = m_fileNames.GetCount();
176     for ( size_t n = 0; n < count; n++ )
177     {
178         if (wxFileName(m_fileNames[n]).IsAbsolute())
179             paths.Add(m_fileNames[n]);
180         else
181             paths.Add(dir + m_fileNames[n]);
182     }
183 }
184
185 void wxFileDialog::GetFilenames(wxArrayString& files) const
186 {
187     files = m_fileNames;
188 }
189
190 void wxFileDialog::SetPath(const wxString& path)
191 {
192     wxString ext;
193     wxFileName::SplitPath(path, &m_dir, &m_fileName, &ext);
194     if ( !ext.empty() )
195         m_fileName << wxT('.') << ext;
196 }
197
198 int wxFileDialog::ShowModal()
199 {
200     WX_TESTING_SHOW_MODAL_HOOK();
201
202     wxAutoNSAutoreleasePool thePool;
203
204     m_fileNames.Empty();
205
206     int nResult;
207
208     if (HasFlag(wxFD_SAVE))
209     {
210         nResult = [GetNSSavePanel()
211                     runModalForDirectory:wxNSStringWithWxString(m_dir)
212                     file:wxNSStringWithWxString(m_fileName)];
213
214         if (nResult == NSOKButton)
215         {
216             m_fileNames.Add(wxStringWithNSString([GetNSSavePanel() filename]));
217             m_path = m_fileNames[0];
218         }
219     }
220     else //m_dialogStyle & wxFD_OPEN
221     {
222         nResult = [(NSOpenPanel*)m_cocoaNSWindow
223                     runModalForDirectory:wxNSStringWithWxString(m_dir)
224                     file:wxNSStringWithWxString(m_fileName)
225                     types:m_wildcards];
226
227         if (nResult == NSOKButton)
228         {
229             for(unsigned i = 0; i < [[(NSOpenPanel*)m_cocoaNSWindow filenames] count]; ++i)
230             {
231                 m_fileNames.Add(wxStringWithNSString([[(NSOpenPanel*)m_cocoaNSWindow filenames] objectAtIndex:(i)]));
232             }
233
234             m_path = m_fileNames[0];
235         }
236     }
237
238     return nResult == NSOKButton ? wxID_OK : wxID_CANCEL;
239 }
240
241 #endif // wxUSE_FILEDLG