]> git.saurik.com Git - wxWidgets.git/blame - src/osx/cocoa/filedlg.mm
Add sanity check on the item number.
[wxWidgets.git] / src / osx / cocoa / filedlg.mm
CommitLineData
0f9b48d1
SC
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"
b822bdc0 33#include "wx/tokenzr.h"
0f9b48d1
SC
34
35#include "wx/osx/private.h"
36
37// ============================================================================
38// implementation
39// ============================================================================
40
4dd9fdf8
SC
41// Open Items:
42// - support for old style MacOS creator / type combos
43// - parameter support for descending into packages as directories (setTreatsFilePackagesAsDirectories)
44
0f9b48d1
SC
45IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase)
46
47wxFileDialog::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)
52{
53}
54
0f9b48d1
SC
55NSArray* GetTypesFromFilter( const wxString filter )
56{
57 NSMutableArray* types = nil;
58 if ( !filter.empty() )
59 {
60 wxArrayString names ;
61 wxArrayString extensions;
bd365871 62
0f9b48d1
SC
63 wxString filter2(filter) ;
64 int filterIndex = 0;
65 bool isName = true ;
66 wxString current ;
67
68 for ( unsigned int i = 0; i < filter2.length() ; i++ )
69 {
70 if ( filter2.GetChar(i) == wxT('|') )
71 {
72 if ( isName )
73 {
74 names.Add( current ) ;
75 }
76 else
77 {
78 extensions.Add( current ) ;
79 ++filterIndex ;
80 }
81
82 isName = !isName ;
83 current = wxEmptyString ;
84 }
85 else
86 {
87 current += filter2.GetChar(i) ;
88 }
89 }
90 // we allow for compatibility reason to have a single filter expression (like *.*) without
91 // an explanatory text, in that case the first part is name and extension at the same time
92
93 wxASSERT_MSG( filterIndex == 0 || !isName , wxT("incorrect format of format string") ) ;
94 if ( current.empty() )
95 extensions.Add( names[filterIndex] ) ;
96 else
97 extensions.Add( current ) ;
98 if ( filterIndex == 0 || isName )
99 names.Add( current ) ;
100
101 ++filterIndex ;
102
103 const size_t extCount = extensions.GetCount();
104 for ( size_t i = 0 ; i < extCount; i++ )
105 {
b822bdc0
SC
106 wxString extensiongroup = extensions[i];
107 wxStringTokenizer tokenizer( extensiongroup , wxT(";") ) ;
108 while ( tokenizer.HasMoreTokens() )
0f9b48d1 109 {
b822bdc0
SC
110 wxString extension = tokenizer.GetNextToken() ;
111 // Remove leading '*'
112 if (extension.length() && (extension.GetChar(0) == '*'))
113 extension = extension.Mid( 1 );
bd365871 114
b822bdc0
SC
115 // Remove leading '.'
116 if (extension.length() && (extension.GetChar(0) == '.'))
117 extension = extension.Mid( 1 );
bd365871 118
b822bdc0
SC
119 if ( extension.IsEmpty() )
120 {
121 if ( types != nil )
122 [types release];
123 return nil;
124 }
125
126 if ( types == nil )
127 types = [[NSMutableArray alloc] init];
bd365871 128
b822bdc0
SC
129 wxCFStringRef cfext(extension);
130 [types addObject: (NSString*)cfext.AsNSString() ];
bd365871 131#if 0
b822bdc0
SC
132 // add support for classic fileType / creator here
133 wxUint32 fileType, creator;
134 // extension -> mactypes
0f9b48d1 135#endif
b822bdc0
SC
136 }
137
0f9b48d1
SC
138 }
139 }
140 return types;
141}
142
bfa92264 143void wxFileDialog::ShowWindowModal()
0f9b48d1 144{
bfa92264
KO
145 wxCFStringRef cf( m_message );
146 wxCFStringRef dir( m_dir );
147 wxCFStringRef file( m_fileName );
148
149 wxNonOwnedWindow* parentWindow = NULL;
150
151 m_modality = wxDIALOG_MODALITY_WINDOW_MODAL;
152
153 if (GetParent())
154 parentWindow = dynamic_cast<wxNonOwnedWindow*>(wxGetTopLevelParent(GetParent()));
155
156 wxASSERT_MSG(parentWindow, "Window modal display requires parent.");
157
158 if (HasFlag(wxFD_SAVE))
159 {
160 NSSavePanel* sPanel = [NSSavePanel savePanel];
161 // makes things more convenient:
162 [sPanel setCanCreateDirectories:YES];
163 [sPanel setMessage:cf.AsNSString()];
164 // if we should be able to descend into pacakges we must somehow
165 // be able to pass this in
166 [sPanel setTreatsFilePackagesAsDirectories:NO];
167 [sPanel setCanSelectHiddenExtension:YES];
168
169 NSWindow* nativeParent = parentWindow->GetWXWindow();
170 ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init];
171 [sheetDelegate setImplementation: this];
172 [sPanel beginSheetForDirectory:dir.AsNSString() file:file.AsNSString()
173 modalForWindow: nativeParent modalDelegate: sheetDelegate
174 didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
175 contextInfo: nil];
176 }
177 else
178 {
179 NSArray* types = GetTypesFromFilter( m_wildCard ) ;
180 NSOpenPanel* oPanel = [NSOpenPanel openPanel];
181 [oPanel setTreatsFilePackagesAsDirectories:NO];
182 [oPanel setCanChooseDirectories:NO];
183 [oPanel setResolvesAliases:YES];
184 [oPanel setCanChooseFiles:YES];
185 [oPanel setMessage:cf.AsNSString()];
186
187 NSWindow* nativeParent = parentWindow->GetWXWindow();
188 ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init];
189 [sheetDelegate setImplementation: this];
190 [oPanel beginSheetForDirectory:dir.AsNSString() file:file.AsNSString()
191 types: types modalForWindow: nativeParent
192 modalDelegate: sheetDelegate
193 didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
194 contextInfo: nil];
195 }
196}
bd365871 197
bfa92264
KO
198int wxFileDialog::ShowModal()
199{
0f9b48d1 200 NSSavePanel *panel = nil;
bd365871 201
0f9b48d1 202 wxCFStringRef cf( m_message );
bd365871 203
1b447793 204 wxCFStringRef dir( m_dir );
0f9b48d1 205 wxCFStringRef file( m_fileName );
bd365871 206
0f9b48d1
SC
207 m_path = wxEmptyString;
208 m_fileNames.Clear();
8b558f12 209 m_paths.Clear();
2efd54a4
SC
210 // since we don't support retrieving the matching filter
211 m_filterIndex = -1;
03647350 212
724999ee
KO
213 wxNonOwnedWindow* parentWindow = NULL;
214 int returnCode = -1;
03647350
VZ
215
216 if (GetParent())
724999ee
KO
217 {
218 parentWindow = dynamic_cast<wxNonOwnedWindow*>(wxGetTopLevelParent(GetParent()));
219 }
bd365871 220
0f9b48d1
SC
221 if (HasFlag(wxFD_SAVE))
222 {
223 NSSavePanel* sPanel = [NSSavePanel savePanel];
224 // makes things more convenient:
225 [sPanel setCanCreateDirectories:YES];
226 [sPanel setMessage:cf.AsNSString()];
4dd9fdf8
SC
227 // if we should be able to descend into pacakges we must somehow
228 // be able to pass this in
0f9b48d1 229 [sPanel setTreatsFilePackagesAsDirectories:NO];
4dd9fdf8 230 [sPanel setCanSelectHiddenExtension:YES];
bd365871 231
0f9b48d1
SC
232 if ( HasFlag(wxFD_OVERWRITE_PROMPT) )
233 {
234 }
440e5cb2 235
bfa92264
KO
236 returnCode = [sPanel runModalForDirectory:dir.AsNSString() file:file.AsNSString() ];
237 ModalFinishedCallback(sPanel, returnCode);
0f9b48d1
SC
238 }
239 else
240 {
241 NSArray* types = GetTypesFromFilter( m_wildCard ) ;
242 NSOpenPanel* oPanel = [NSOpenPanel openPanel];
243 [oPanel setTreatsFilePackagesAsDirectories:NO];
244 [oPanel setCanChooseDirectories:NO];
245 [oPanel setResolvesAliases:YES];
246 [oPanel setCanChooseFiles:YES];
247 [oPanel setMessage:cf.AsNSString()];
bd365871 248
bfa92264 249 returnCode = [oPanel runModalForDirectory:dir.AsNSString()
724999ee 250 file:file.AsNSString() types:types];
bfa92264
KO
251
252 ModalFinishedCallback(oPanel, returnCode);
253
254 if ( types != nil )
255 [types release];
256 }
257
258 return GetReturnCode();
259}
260
261void wxFileDialog::ModalFinishedCallback(void* panel, int returnCode)
262{
263 int result = wxID_CANCEL;
264 if (HasFlag(wxFD_SAVE))
265 {
266 if (returnCode == NSOKButton )
267 {
268 NSSavePanel* sPanel = (NSSavePanel*)panel;
269 result = wxID_OK;
270
271 m_path = wxCFStringRef::AsString([sPanel filename]);
272 m_fileName = wxFileNameFromPath(m_path);
273 m_dir = wxPathOnly( m_path );
724999ee 274 }
bfa92264
KO
275 }
276 else
277 {
278 NSOpenPanel* oPanel = (NSOpenPanel*)panel;
b2c47ad3 279 if (returnCode == NSOKButton )
0f9b48d1
SC
280 {
281 panel = oPanel;
282 result = wxID_OK;
283 NSArray* filenames = [oPanel filenames];
284 for ( size_t i = 0 ; i < [filenames count] ; ++ i )
285 {
f66ecdc4 286 wxString fnstr = wxCFStringRef::AsString([filenames objectAtIndex:i]);
0f9b48d1
SC
287 m_paths.Add( fnstr );
288 m_fileNames.Add( wxFileNameFromPath(fnstr) );
289 if ( i == 0 )
290 {
291 m_path = fnstr;
292 m_fileName = wxFileNameFromPath(fnstr);
293 m_dir = wxPathOnly( fnstr );
294 }
295 }
296 }
0f9b48d1 297 }
bfa92264
KO
298 SetReturnCode(result);
299
300 if (GetModality() == wxDIALOG_MODALITY_WINDOW_MODAL)
301 SendWindowModalDialogEvent ( wxEVT_WINDOW_MODAL_DIALOG_CLOSED );
0f9b48d1
SC
302}
303
0f9b48d1 304#endif // wxUSE_FILEDLG