]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/filedlg.mm
fixed a bug caused by passing a wxChar[] buffer to a function taking a wxString;...
[wxWidgets.git] / src / osx / 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: filedlg.mm 40007 2006-07-05 13:10:46Z SC $
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/osx/private.h"
35
36 // ============================================================================
37 // implementation
38 // ============================================================================
39
40 IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase)
41
42 wxFileDialog::wxFileDialog(
43 wxWindow *parent, const wxString& message,
44 const wxString& defaultDir, const wxString& defaultFileName, const wxString& wildCard,
45 long style, const wxPoint& pos, const wxSize& sz, const wxString& name)
46 : wxFileDialogBase(parent, message, defaultDir, defaultFileName, wildCard, style, pos, sz, name)
47 {
48 }
49
50
51 NSArray* GetTypesFromFilter( const wxString filter )
52 {
53 NSMutableArray* types = nil;
54 if ( !filter.empty() )
55 {
56 wxArrayString names ;
57 wxArrayString extensions;
58
59 wxString filter2(filter) ;
60 int filterIndex = 0;
61 bool isName = true ;
62 wxString current ;
63
64 for ( unsigned int i = 0; i < filter2.length() ; i++ )
65 {
66 if ( filter2.GetChar(i) == wxT('|') )
67 {
68 if ( isName )
69 {
70 names.Add( current ) ;
71 }
72 else
73 {
74 extensions.Add( current ) ;
75 ++filterIndex ;
76 }
77
78 isName = !isName ;
79 current = wxEmptyString ;
80 }
81 else
82 {
83 current += filter2.GetChar(i) ;
84 }
85 }
86 // we allow for compatibility reason to have a single filter expression (like *.*) without
87 // an explanatory text, in that case the first part is name and extension at the same time
88
89 wxASSERT_MSG( filterIndex == 0 || !isName , wxT("incorrect format of format string") ) ;
90 if ( current.empty() )
91 extensions.Add( names[filterIndex] ) ;
92 else
93 extensions.Add( current ) ;
94 if ( filterIndex == 0 || isName )
95 names.Add( current ) ;
96
97 ++filterIndex ;
98
99 const size_t extCount = extensions.GetCount();
100 for ( size_t i = 0 ; i < extCount; i++ )
101 {
102 wxString extension = extensions[i];
103
104 // Remove leading '*'
105 if (extension.length() && (extension.GetChar(0) == '*'))
106 extension = extension.Mid( 1 );
107
108 // Remove leading '.'
109 if (extension.length() && (extension.GetChar(0) == '.'))
110 extension = extension.Mid( 1 );
111
112 if ( extension.IsEmpty() )
113 {
114 if ( types != nil )
115 [types release];
116 return nil;
117 }
118
119
120 if ( types == nil )
121 types = [[NSMutableArray alloc] init];
122
123 wxCFStringRef cfext(extension);
124 [types addObject: (NSString*)cfext.AsNSString() ];
125 #if 0
126 wxUint32 fileType, creator;
127
128 // extension -> mactypes
129 #endif
130 }
131 }
132 return types;
133 }
134
135 int wxFileDialog::ShowModal()
136 {
137 int result = wxID_CANCEL;
138
139 NSSavePanel *panel = nil;
140
141 wxCFStringRef cf( m_message );
142
143 wxCFStringRef dir( m_path );
144 wxCFStringRef file( m_fileName );
145
146 m_path = wxEmptyString;
147 m_fileNames.Clear();
148
149 if (HasFlag(wxFD_SAVE))
150 {
151 NSSavePanel* sPanel = [NSSavePanel savePanel];
152 // makes things more convenient:
153 [sPanel setCanCreateDirectories:YES];
154 [sPanel setMessage:cf.AsNSString()];
155 [sPanel setTreatsFilePackagesAsDirectories:NO];
156
157 if ( HasFlag(wxFD_OVERWRITE_PROMPT) )
158 {
159 }
160
161 if ( [sPanel runModalForDirectory:dir.AsNSString() file:file.AsNSString() ] == NSOKButton )
162 {
163 panel = sPanel;
164 result = wxID_OK;
165
166 wxCFStringRef filename( [[sPanel filename] retain] );
167
168 m_path = filename.AsString();
169 m_fileName = wxFileNameFromPath(m_path);
170 m_dir = wxPathOnly( m_path );
171 }
172 }
173 else
174 {
175 NSArray* types = GetTypesFromFilter( m_wildCard ) ;
176 NSOpenPanel* oPanel = [NSOpenPanel openPanel];
177 [oPanel setTreatsFilePackagesAsDirectories:NO];
178 [oPanel setCanChooseDirectories:NO];
179 [oPanel setResolvesAliases:YES];
180 [oPanel setCanChooseFiles:YES];
181 [oPanel setMessage:cf.AsNSString()];
182
183 if ( [oPanel runModalForDirectory:dir.AsNSString() file:file.AsNSString() types:types] == NSOKButton )
184 {
185 panel = oPanel;
186 result = wxID_OK;
187 NSArray* filenames = [oPanel filenames];
188 for ( size_t i = 0 ; i < [filenames count] ; ++ i )
189 {
190 wxCFStringRef filename( [(NSString*) [filenames objectAtIndex:i] retain] );
191 wxString fnstr = filename.AsString();
192 m_paths.Add( fnstr );
193 m_fileNames.Add( wxFileNameFromPath(fnstr) );
194 if ( i == 0 )
195 {
196 m_path = fnstr;
197 m_fileName = wxFileNameFromPath(fnstr);
198 m_dir = wxPathOnly( fnstr );
199 }
200 }
201 }
202 if ( types != nil )
203 [types release];
204 }
205
206 return result;
207 }
208
209 #if 0
210
211 wxASSERT(CreateBase(parent,wxID_ANY,pos,wxDefaultSize,style,wxDefaultValidator,wxDialogNameStr));
212
213 if ( parent )
214 parent->AddChild(this);
215
216 m_cocoaNSWindow = nil;
217 m_cocoaNSView = nil;
218
219 //Init the wildcard array
220 m_wildcards = [[NSMutableArray alloc] initWithCapacity:0];
221
222 //If the user requests to save - use a NSSavePanel
223 //else use a NSOpenPanel
224 if (HasFlag(wxFD_SAVE))
225 {
226 SetNSPanel([NSSavePanel savePanel]);
227
228 [GetNSSavePanel() setTitle:wxNSStringWithWxString(message)];
229
230 [GetNSSavePanel() setPrompt:@"Save"];
231 [GetNSSavePanel() setTreatsFilePackagesAsDirectories:YES];
232 [GetNSSavePanel() setCanSelectHiddenExtension:YES];
233
234 // Cached as per-app in obj-c
235 // [GetNSSavePanel() setExtensionHidden:YES];
236
237 //
238 // NB: Note that only Panther supports wildcards
239 // with save dialogs - not that wildcards in save
240 // dialogs are all that useful, anyway :)
241 //
242 }
243 else //m_dialogStyle & wxFD_OPEN
244 {
245 SetNSPanel([NSOpenPanel openPanel]);
246 [m_cocoaNSWindow setTitle:wxNSStringWithWxString(message)];
247
248 [(NSOpenPanel*)m_cocoaNSWindow setAllowsMultipleSelection:(HasFlag(wxFD_MULTIPLE))];
249 [(NSOpenPanel*)m_cocoaNSWindow setResolvesAliases:YES];
250 [(NSOpenPanel*)m_cocoaNSWindow setCanChooseFiles:YES];
251 [(NSOpenPanel*)m_cocoaNSWindow setCanChooseDirectories:NO];
252 [GetNSSavePanel() setPrompt:@"Open"];
253
254 //convert wildcards - open panel only takes file extensions -
255 //no actual wildcards here :)
256 size_t lastwcpos = 0;
257 bool bDescription = true;
258 size_t i;
259 for(i = wildCard.find('|');
260 i != wxString::npos;
261 i = wildCard.find('|', lastwcpos+1))
262 {
263 size_t oldi = i;
264
265 if(!bDescription)
266 {
267 bDescription = !bDescription;
268
269 //work backwards looking for a period
270 while(i != lastwcpos && wildCard[--i] != '.') {}
271
272 if(i == lastwcpos)
273 {
274 //no extension - can't use this wildcard
275 lastwcpos = oldi;
276 continue;
277 }
278
279 [m_wildcards addObject:wxNSStringWithWxString(wildCard.substr(i+1, oldi-i-1))];
280 }
281 else
282 bDescription = !bDescription;
283 lastwcpos = oldi;
284 }
285
286 if (!bDescription)
287 {
288 //get last wildcard
289 size_t oldi = wildCard.length();
290 i = oldi;
291
292 //work backwards looking for a period
293 while(i != lastwcpos && wildCard[--i] != '.') {}
294
295 if(i != lastwcpos)
296 [m_wildcards addObject:wxNSStringWithWxString(wildCard.substr(i+1, oldi-i-1))];
297 }
298
299 if ([m_wildcards count] == 0)
300 {
301 [m_wildcards release];
302 m_wildcards = nil;
303 }
304 }
305 }
306
307 wxFileDialog::~wxFileDialog()
308 {
309 [m_wildcards release];
310 }
311
312 void wxFileDialog::GetPaths(wxArrayString& paths) const
313 {
314 paths.Empty();
315
316 wxString dir(m_dir);
317 if ( m_dir.Last() != _T('\\') )
318 dir += _T('\\');
319
320 size_t count = m_fileNames.GetCount();
321 for ( size_t n = 0; n < count; n++ )
322 {
323 if (wxFileName(m_fileNames[n]).IsAbsolute())
324 paths.Add(m_fileNames[n]);
325 else
326 paths.Add(dir + m_fileNames[n]);
327 }
328 }
329
330 void wxFileDialog::GetFilenames(wxArrayString& files) const
331 {
332 files = m_fileNames;
333 }
334
335 void wxFileDialog::SetPath(const wxString& path)
336 {
337 wxString ext;
338 wxSplitPath(path, &m_dir, &m_fileName, &ext);
339 if ( !ext.empty() )
340 m_fileName << _T('.') << ext;
341 }
342
343 int wxFileDialog::ShowModal()
344 {
345 wxAutoNSAutoreleasePool thePool;
346
347 m_fileNames.Empty();
348
349 int nResult;
350
351 if (HasFlag(wxFD_SAVE))
352 {
353 nResult = [GetNSSavePanel()
354 runModalForDirectory:wxNSStringWithWxString(m_dir)
355 file:wxNSStringWithWxString(m_fileName)];
356
357 if (nResult == NSOKButton)
358 {
359 m_fileNames.Add(wxStringWithNSString([GetNSSavePanel() filename]));
360 m_path = m_fileNames[0];
361 }
362 }
363 else //m_dialogStyle & wxFD_OPEN
364 {
365 nResult = [(NSOpenPanel*)m_cocoaNSWindow
366 runModalForDirectory:wxNSStringWithWxString(m_dir)
367 file:wxNSStringWithWxString(m_fileName)
368 types:m_wildcards];
369
370 if (nResult == NSOKButton)
371 {
372 for(unsigned i = 0; i < [[(NSOpenPanel*)m_cocoaNSWindow filenames] count]; ++i)
373 {
374 m_fileNames.Add(wxStringWithNSString([[(NSOpenPanel*)m_cocoaNSWindow filenames] objectAtIndex:(i)]));
375 }
376
377 m_path = m_fileNames[0];
378 }
379 }
380
381 return nResult == NSOKButton ? wxID_OK : wxID_CANCEL;
382 }
383
384 #endif
385
386 #endif // wxUSE_FILEDLG