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"
33 #include "wx/tokenzr.h"
35 #include "wx/osx/private.h"
37 // ============================================================================
39 // ============================================================================
42 // - support for old style MacOS creator / type combos
43 // - parameter support for descending into packages as directories (setTreatsFilePackagesAsDirectories)
45 IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase)
47 wxFileDialog::wxFileDialog(
48 wxWindow *parent, const wxString& message,
49 const wxString& defaultDir, const wxString& defaultFileName, const wxString& wildCard,
50 long style, const wxPoint& pos, const wxSize& sz, const wxString& name)
51 : wxFileDialogBase(parent, message, defaultDir, defaultFileName, wildCard, style, pos, sz, name)
55 bool wxFileDialog::SupportsExtraControl() const
60 NSArray* CopyTypesFromFilter( const wxString filter )
62 NSMutableArray* types = nil;
63 if ( !filter.empty() )
66 wxArrayString extensions;
68 wxString filter2(filter) ;
73 for ( unsigned int i = 0; i < filter2.length() ; i++ )
75 if ( filter2.GetChar(i) == wxT('|') )
79 names.Add( current ) ;
83 extensions.Add( current ) ;
88 current = wxEmptyString ;
92 current += filter2.GetChar(i) ;
95 // we allow for compatibility reason to have a single filter expression (like *.*) without
96 // an explanatory text, in that case the first part is name and extension at the same time
98 wxASSERT_MSG( filterIndex == 0 || !isName , wxT("incorrect format of format string") ) ;
99 if ( current.empty() )
100 extensions.Add( names[filterIndex] ) ;
102 extensions.Add( current ) ;
103 if ( filterIndex == 0 || isName )
104 names.Add( current ) ;
108 const size_t extCount = extensions.GetCount();
109 for ( size_t i = 0 ; i < extCount; i++ )
111 wxString extensiongroup = extensions[i];
112 wxStringTokenizer tokenizer( extensiongroup , wxT(";") ) ;
113 while ( tokenizer.HasMoreTokens() )
115 wxString extension = tokenizer.GetNextToken() ;
116 // Remove leading '*'
117 if (extension.length() && (extension.GetChar(0) == '*'))
118 extension = extension.Mid( 1 );
120 // Remove leading '.'
121 if (extension.length() && (extension.GetChar(0) == '.'))
122 extension = extension.Mid( 1 );
124 // Remove leading '*', this is for handling *.*
125 if (extension.length() && (extension.GetChar(0) == '*'))
126 extension = extension.Mid( 1 );
128 if ( extension.IsEmpty() )
136 types = [[NSMutableArray alloc] init];
138 wxCFStringRef cfext(extension);
139 [types addObject: (NSString*)cfext.AsNSString() ];
141 // add support for classic fileType / creator here
142 wxUint32 fileType, creator;
143 // extension -> mactypes
152 void wxFileDialog::ShowWindowModal()
154 wxCFStringRef cf( m_message );
155 wxCFStringRef dir( m_dir );
156 wxCFStringRef file( m_fileName );
158 wxNonOwnedWindow* parentWindow = NULL;
160 m_modality = wxDIALOG_MODALITY_WINDOW_MODAL;
163 parentWindow = dynamic_cast<wxNonOwnedWindow*>(wxGetTopLevelParent(GetParent()));
165 wxASSERT_MSG(parentWindow, "Window modal display requires parent.");
167 NSArray* types = CopyTypesFromFilter( m_wildCard ) ;
168 if (HasFlag(wxFD_SAVE))
170 NSSavePanel* sPanel = [NSSavePanel savePanel];
172 SetupExtraControls(sPanel);
174 // makes things more convenient:
175 [sPanel setCanCreateDirectories:YES];
176 [sPanel setMessage:cf.AsNSString()];
177 // if we should be able to descend into pacakges we must somehow
178 // be able to pass this in
179 [sPanel setTreatsFilePackagesAsDirectories:NO];
180 [sPanel setCanSelectHiddenExtension:YES];
181 [sPanel setAllowedFileTypes:types];
182 [sPanel setAllowsOtherFileTypes:NO];
184 NSWindow* nativeParent = parentWindow->GetWXWindow();
185 ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init];
186 [sheetDelegate setImplementation: this];
187 [sPanel beginSheetForDirectory:dir.AsNSString() file:file.AsNSString()
188 modalForWindow: nativeParent modalDelegate: sheetDelegate
189 didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
194 NSOpenPanel* oPanel = [NSOpenPanel openPanel];
196 SetupExtraControls(oPanel);
198 [oPanel setTreatsFilePackagesAsDirectories:NO];
199 [oPanel setCanChooseDirectories:NO];
200 [oPanel setResolvesAliases:YES];
201 [oPanel setCanChooseFiles:YES];
202 [oPanel setMessage:cf.AsNSString()];
203 if ( HasFlag(wxFD_MULTIPLE) )
204 [oPanel setAllowsMultipleSelection:YES];
206 NSWindow* nativeParent = parentWindow->GetWXWindow();
207 ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init];
208 [sheetDelegate setImplementation: this];
209 [oPanel beginSheetForDirectory:dir.AsNSString() file:file.AsNSString()
210 types: types modalForWindow: nativeParent
211 modalDelegate: sheetDelegate
212 didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
219 void wxFileDialog::SetupExtraControls(WXWindow nativeWindow)
221 NSSavePanel* panel = (NSSavePanel*) nativeWindow;
223 wxNonOwnedWindow::Create( GetParent(), nativeWindow );
225 if (HasExtraControlCreator())
227 CreateExtraControl();
228 wxWindow* control = GetExtraControl();
231 NSView* accView = control->GetHandle();
232 [accView removeFromSuperview];
233 [panel setAccessoryView:accView];
237 [panel setAccessoryView:nil];
242 int wxFileDialog::ShowModal()
244 wxCFStringRef cf( m_message );
246 wxCFStringRef dir( m_dir );
247 wxCFStringRef file( m_fileName );
249 m_path = wxEmptyString;
252 // since we don't support retrieving the matching filter
255 wxNonOwnedWindow* parentWindow = NULL;
260 parentWindow = dynamic_cast<wxNonOwnedWindow*>(wxGetTopLevelParent(GetParent()));
263 NSArray* types = CopyTypesFromFilter( m_wildCard ) ;
264 if (HasFlag(wxFD_SAVE))
266 NSSavePanel* sPanel = [NSSavePanel savePanel];
268 SetupExtraControls(sPanel);
270 // makes things more convenient:
271 [sPanel setCanCreateDirectories:YES];
272 [sPanel setMessage:cf.AsNSString()];
273 // if we should be able to descend into pacakges we must somehow
274 // be able to pass this in
275 [sPanel setTreatsFilePackagesAsDirectories:NO];
276 [sPanel setCanSelectHiddenExtension:YES];
277 [sPanel setAllowedFileTypes:types];
278 [sPanel setAllowsOtherFileTypes:NO];
280 if ( HasFlag(wxFD_OVERWRITE_PROMPT) )
284 returnCode = [sPanel runModalForDirectory:dir.AsNSString() file:file.AsNSString() ];
285 ModalFinishedCallback(sPanel, returnCode);
288 [sPanel setAccessoryView:nil];
292 NSOpenPanel* oPanel = [NSOpenPanel openPanel];
294 SetupExtraControls(oPanel);
296 [oPanel setTreatsFilePackagesAsDirectories:NO];
297 [oPanel setCanChooseDirectories:NO];
298 [oPanel setResolvesAliases:YES];
299 [oPanel setCanChooseFiles:YES];
300 [oPanel setMessage:cf.AsNSString()];
301 if ( HasFlag(wxFD_MULTIPLE) )
302 [oPanel setAllowsMultipleSelection:YES];
304 returnCode = [oPanel runModalForDirectory:dir.AsNSString()
305 file:file.AsNSString() types:types];
307 ModalFinishedCallback(oPanel, returnCode);
310 [oPanel setAccessoryView:nil];
316 return GetReturnCode();
319 void wxFileDialog::ModalFinishedCallback(void* panel, int returnCode)
321 int result = wxID_CANCEL;
322 if (HasFlag(wxFD_SAVE))
324 if (returnCode == NSOKButton )
326 NSSavePanel* sPanel = (NSSavePanel*)panel;
329 m_path = wxCFStringRef::AsString([sPanel filename]);
330 m_fileName = wxFileNameFromPath(m_path);
331 m_dir = wxPathOnly( m_path );
336 NSOpenPanel* oPanel = (NSOpenPanel*)panel;
337 if (returnCode == NSOKButton )
341 NSArray* filenames = [oPanel filenames];
342 for ( size_t i = 0 ; i < [filenames count] ; ++ i )
344 wxString fnstr = wxCFStringRef::AsString([filenames objectAtIndex:i]);
345 m_paths.Add( fnstr );
346 m_fileNames.Add( wxFileNameFromPath(fnstr) );
350 m_fileName = wxFileNameFromPath(fnstr);
351 m_dir = wxPathOnly( fnstr );
356 SetReturnCode(result);
358 if (GetModality() == wxDIALOG_MODALITY_WINDOW_MODAL)
359 SendWindowModalDialogEvent ( wxEVT_WINDOW_MODAL_DIALOG_CLOSED );
361 [(NSSavePanel*) panel setAccessoryView:nil];
364 #endif // wxUSE_FILEDLG