1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/cocoa/filedlg.mm
3 // Purpose: wxFileDialog for wxCocoa
7 // RCS-ID: $Id: filedlg.mm 40007 2006-07-05 13:10:46Z SC $
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
25 #include "wx/filedlg.h"
28 #include "wx/msgdlg.h"
32 #include "wx/filename.h"
34 #include "wx/osx/private.h"
36 // ============================================================================
38 // ============================================================================
40 IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase)
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)
51 NSArray* GetTypesFromFilter( const wxString filter )
53 NSMutableArray* types = nil;
54 if ( !filter.empty() )
57 wxArrayString extensions;
59 wxString filter2(filter) ;
64 for ( unsigned int i = 0; i < filter2.length() ; i++ )
66 if ( filter2.GetChar(i) == wxT('|') )
70 names.Add( current ) ;
74 extensions.Add( current ) ;
79 current = wxEmptyString ;
83 current += filter2.GetChar(i) ;
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
89 wxASSERT_MSG( filterIndex == 0 || !isName , wxT("incorrect format of format string") ) ;
90 if ( current.empty() )
91 extensions.Add( names[filterIndex] ) ;
93 extensions.Add( current ) ;
94 if ( filterIndex == 0 || isName )
95 names.Add( current ) ;
99 const size_t extCount = extensions.GetCount();
100 for ( size_t i = 0 ; i < extCount; i++ )
102 wxString extension = extensions[i];
104 // Remove leading '*'
105 if (extension.length() && (extension.GetChar(0) == '*'))
106 extension = extension.Mid( 1 );
108 // Remove leading '.'
109 if (extension.length() && (extension.GetChar(0) == '.'))
110 extension = extension.Mid( 1 );
112 if ( extension.IsEmpty() )
121 types = [[NSMutableArray alloc] init];
123 wxCFStringRef cfext(extension);
124 [types addObject: (NSString*)cfext.AsNSString() ];
126 wxUint32 fileType, creator;
128 // extension -> mactypes
135 int wxFileDialog::ShowModal()
137 int result = wxID_CANCEL;
139 NSSavePanel *panel = nil;
141 wxCFStringRef cf( m_message );
143 wxCFStringRef dir( m_path );
144 wxCFStringRef file( m_fileName );
146 m_path = wxEmptyString;
149 if (HasFlag(wxFD_SAVE))
151 NSSavePanel* sPanel = [NSSavePanel savePanel];
152 // makes things more convenient:
153 [sPanel setCanCreateDirectories:YES];
154 [sPanel setMessage:cf.AsNSString()];
155 [sPanel setTreatsFilePackagesAsDirectories:NO];
157 if ( HasFlag(wxFD_OVERWRITE_PROMPT) )
161 if ( [sPanel runModalForDirectory:dir.AsNSString() file:file.AsNSString() ] == NSOKButton )
166 wxCFStringRef filename( [[sPanel filename] retain] );
168 m_path = filename.AsString();
169 m_fileName = wxFileNameFromPath(m_path);
170 m_dir = wxPathOnly( m_path );
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()];
183 if ( [oPanel runModalForDirectory:dir.AsNSString() file:file.AsNSString() types:types] == NSOKButton )
187 NSArray* filenames = [oPanel filenames];
188 for ( size_t i = 0 ; i < [filenames count] ; ++ i )
190 wxCFStringRef filename( [(NSString*) [filenames objectAtIndex:i] retain] );
191 wxString fnstr = filename.AsString();
192 m_paths.Add( fnstr );
193 m_fileNames.Add( wxFileNameFromPath(fnstr) );
197 m_fileName = wxFileNameFromPath(fnstr);
198 m_dir = wxPathOnly( fnstr );
211 wxASSERT(CreateBase(parent,wxID_ANY,pos,wxDefaultSize,style,wxDefaultValidator,wxDialogNameStr));
214 parent->AddChild(this);
216 m_cocoaNSWindow = nil;
219 //Init the wildcard array
220 m_wildcards = [[NSMutableArray alloc] initWithCapacity:0];
222 //If the user requests to save - use a NSSavePanel
223 //else use a NSOpenPanel
224 if (HasFlag(wxFD_SAVE))
226 SetNSPanel([NSSavePanel savePanel]);
228 [GetNSSavePanel() setTitle:wxNSStringWithWxString(message)];
230 [GetNSSavePanel() setPrompt:@"Save"];
231 [GetNSSavePanel() setTreatsFilePackagesAsDirectories:YES];
232 [GetNSSavePanel() setCanSelectHiddenExtension:YES];
234 // Cached as per-app in obj-c
235 // [GetNSSavePanel() setExtensionHidden:YES];
238 // NB: Note that only Panther supports wildcards
239 // with save dialogs - not that wildcards in save
240 // dialogs are all that useful, anyway :)
243 else //m_dialogStyle & wxFD_OPEN
245 SetNSPanel([NSOpenPanel openPanel]);
246 [m_cocoaNSWindow setTitle:wxNSStringWithWxString(message)];
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"];
254 //convert wildcards - open panel only takes file extensions -
255 //no actual wildcards here :)
256 size_t lastwcpos = 0;
257 bool bDescription = true;
259 for(i = wildCard.find('|');
261 i = wildCard.find('|', lastwcpos+1))
267 bDescription = !bDescription;
269 //work backwards looking for a period
270 while(i != lastwcpos && wildCard[--i] != '.') {}
274 //no extension - can't use this wildcard
279 [m_wildcards addObject:wxNSStringWithWxString(wildCard.substr(i+1, oldi-i-1))];
282 bDescription = !bDescription;
289 size_t oldi = wildCard.length();
292 //work backwards looking for a period
293 while(i != lastwcpos && wildCard[--i] != '.') {}
296 [m_wildcards addObject:wxNSStringWithWxString(wildCard.substr(i+1, oldi-i-1))];
299 if ([m_wildcards count] == 0)
301 [m_wildcards release];
307 wxFileDialog::~wxFileDialog()
309 [m_wildcards release];
312 void wxFileDialog::GetPaths(wxArrayString& paths) const
317 if ( m_dir.Last() != _T('\\') )
320 size_t count = m_fileNames.GetCount();
321 for ( size_t n = 0; n < count; n++ )
323 if (wxFileName(m_fileNames[n]).IsAbsolute())
324 paths.Add(m_fileNames[n]);
326 paths.Add(dir + m_fileNames[n]);
330 void wxFileDialog::GetFilenames(wxArrayString& files) const
335 void wxFileDialog::SetPath(const wxString& path)
338 wxSplitPath(path, &m_dir, &m_fileName, &ext);
340 m_fileName << _T('.') << ext;
343 int wxFileDialog::ShowModal()
345 wxAutoNSAutoreleasePool thePool;
351 if (HasFlag(wxFD_SAVE))
353 nResult = [GetNSSavePanel()
354 runModalForDirectory:wxNSStringWithWxString(m_dir)
355 file:wxNSStringWithWxString(m_fileName)];
357 if (nResult == NSOKButton)
359 m_fileNames.Add(wxStringWithNSString([GetNSSavePanel() filename]));
360 m_path = m_fileNames[0];
363 else //m_dialogStyle & wxFD_OPEN
365 nResult = [(NSOpenPanel*)m_cocoaNSWindow
366 runModalForDirectory:wxNSStringWithWxString(m_dir)
367 file:wxNSStringWithWxString(m_fileName)
370 if (nResult == NSOKButton)
372 for(unsigned i = 0; i < [[(NSOpenPanel*)m_cocoaNSWindow filenames] count]; ++i)
374 m_fileNames.Add(wxStringWithNSString([[(NSOpenPanel*)m_cocoaNSWindow filenames] objectAtIndex:(i)]));
377 m_path = m_fileNames[0];
381 return nResult == NSOKButton ? wxID_OK : wxID_CANCEL;
386 #endif // wxUSE_FILEDLG