CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / widget / src / cocoa / nsFilePicker.mm
blob3ad5e856a9693caea026e036d13d43766b7a1677
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  * http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  *
15  * The Original Code is Mozilla browser.
16  *
17  * The Initial Developer of the Original Code is Netscape
18  * Communications Corporation. Portions created by Netscape are
19  * Copyright (C) 1999 Netscape Communications Corporation. All
20  * Rights Reserved.
21  *
22  * Contributor(s):
23  *   Stuart Parmenter <pavlov@netscape.com>
24  *   Steve Dagley <sdagley@netscape.com>
25  *   David Haas <haasd@cae.wisc.edu>
26  *   Simon Fraser <sfraser@netscape.com>
27  *   Josh Aas <josh@mozilla.com>
28  *
29  * Alternatively, the contents of this file may be used under the terms of
30  * either the GNU General Public License Version 2 or later (the "GPL"), or
31  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32  * in which case the provisions of the GPL or the LGPL are applicable instead
33  * of those above. If you wish to allow use of your version of this file only
34  * under the terms of either the GPL or the LGPL, and not to allow others to
35  * use your version of this file under the terms of the MPL, indicate your
36  * decision by deleting the provisions above and replace them with the notice
37  * and other provisions required by the GPL or the LGPL. If you do not delete
38  * the provisions above, a recipient may use your version of this file under
39  * the terms of any one of the MPL, the GPL or the LGPL.
40  *
41  * ***** END LICENSE BLOCK ***** */
43 #import <Cocoa/Cocoa.h>
45 #include "nsFilePicker.h"
46 #include "nsObjCExceptions.h"
47 #include "nsCOMPtr.h"
48 #include "nsReadableUtils.h"
49 #include "nsNetUtil.h"
50 #include "nsIComponentManager.h"
51 #include "nsILocalFile.h"
52 #include "nsILocalFileMac.h"
53 #include "nsIURL.h"
54 #include "nsArrayEnumerator.h"
55 #include "nsIStringBundle.h"
56 #include "nsIPrefService.h"
57 #include "nsIPrefBranch.h"
58 #include "nsCocoaUtils.h"
60 const float kAccessoryViewPadding = 5;
61 const int   kSaveTypeControlTag = 1;
62 const char  kLastTypeIndexPref[] = "filepicker.lastTypeIndex";
64 static PRBool gCallSecretHiddenFileAPI = PR_FALSE;
65 const char kShowHiddenFilesPref[] = "filepicker.showHiddenFiles";
67 NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker)
69 // We never want to call the secret show hidden files API unless the pref
70 // has been set. Once the pref has been set we always need to call it even
71 // if it disappears so that we stop showing hidden files if a user deletes
72 // the pref. If the secret API was used once and things worked out it should
73 // continue working for subsequent calls so the user is at no more risk.
74 static void SetShowHiddenFileState(NSSavePanel* panel)
76   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
78   PRBool show = PR_FALSE;
79   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
80   if (prefs) {
81     nsresult rv = prefs->GetBoolPref(kShowHiddenFilesPref, &show);
82     if (NS_SUCCEEDED(rv))
83       gCallSecretHiddenFileAPI = PR_TRUE;
84   }
86   if (gCallSecretHiddenFileAPI) {
87     // invoke a method to get a Cocoa-internal nav view
88     SEL navViewSelector = @selector(_navView);
89     NSMethodSignature* navViewSignature = [panel methodSignatureForSelector:navViewSelector];
90     if (!navViewSignature)
91       return;
92     NSInvocation* navViewInvocation = [NSInvocation invocationWithMethodSignature:navViewSignature];
93     [navViewInvocation setSelector:navViewSelector];
94     [navViewInvocation setTarget:panel];
95     [navViewInvocation invoke];
97     // get the returned nav view
98     id navView = nil;
99     [navViewInvocation getReturnValue:&navView];
101     // invoke the secret show hidden file state method on the nav view
102     SEL showHiddenFilesSelector = @selector(setShowsHiddenFiles:);
103     NSMethodSignature* showHiddenFilesSignature = [navView methodSignatureForSelector:showHiddenFilesSelector];
104     if (!showHiddenFilesSignature)
105       return;
106     NSInvocation* showHiddenFilesInvocation = [NSInvocation invocationWithMethodSignature:showHiddenFilesSignature];
107     [showHiddenFilesInvocation setSelector:showHiddenFilesSelector];
108     [showHiddenFilesInvocation setTarget:navView];
109     [showHiddenFilesInvocation setArgument:&show atIndex:2];
110     [showHiddenFilesInvocation invoke];
111   }
113   NS_OBJC_END_TRY_ABORT_BLOCK;
116 nsFilePicker::nsFilePicker()
117 : mMode(0)
118 , mSelectedTypeIndex(0)
122 nsFilePicker::~nsFilePicker()
126 void
127 nsFilePicker::InitNative(nsIWidget *aParent, const nsAString& aTitle,
128                          PRInt16 aMode)
130   mTitle = aTitle;
131   mMode = aMode;
133   // read in initial type index from prefs
134   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
135   if (prefs) {
136     int prefIndex;
137     if (NS_SUCCEEDED(prefs->GetIntPref(kLastTypeIndexPref, &prefIndex)))
138       mSelectedTypeIndex = prefIndex;
139   }
142 NSView* nsFilePicker::GetAccessoryView()
144   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
146   NSView* accessoryView = [[[NSView alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)] autorelease];
148   // get the localized string for "Save As:"
149   NSString* saveAsLabel = @"Save As:"; // backup in case we can't get a localized string
150   nsCOMPtr<nsIStringBundleService> sbs = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
151   nsCOMPtr<nsIStringBundle> bundle;
152   nsresult rv = sbs->CreateBundle("chrome://global/locale/filepicker.properties", getter_AddRefs(bundle));
153   if (NS_SUCCEEDED(rv)) {
154     nsXPIDLString label;
155     bundle->GetStringFromName(NS_LITERAL_STRING("saveAsLabel").get(), getter_Copies(label));
156     if (label)
157       saveAsLabel = [NSString stringWithCharacters:label.get() length:label.Length()];
158   }
160   // set up label text field
161   NSTextField* textField = [[[NSTextField alloc] init] autorelease];
162   [textField setEditable:NO];
163   [textField setSelectable:NO];
164   [textField setDrawsBackground:NO];
165   [textField setBezeled:NO];
166   [textField setBordered:NO];
167   [textField setFont:[NSFont labelFontOfSize:13.0]];
168   [textField setStringValue:saveAsLabel];
169   [textField setTag:0];
170   [textField sizeToFit];
172   // set up popup button
173   NSPopUpButton* popupButton = [[[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 0, 0) pullsDown:NO] autorelease];
174   PRUint32 numMenuItems = mTitles.Length();
175   for (PRUint32 i = 0; i < numMenuItems; i++) {
176     const nsString& currentTitle = mTitles[i];
177     NSString *titleString;
178     if (currentTitle.IsEmpty()) {
179       const nsString& currentFilter = mFilters[i];
180       titleString = [[NSString alloc] initWithCharacters:currentFilter.get()
181                                                   length:currentFilter.Length()];
182     }
183     else {
184       titleString = [[NSString alloc] initWithCharacters:currentTitle.get()
185                                                   length:currentTitle.Length()];
186     }
187     [popupButton addItemWithTitle:titleString];
188     [titleString release];
189   }
190   if (mSelectedTypeIndex >= 0 && (PRUint32)mSelectedTypeIndex < numMenuItems)
191     [popupButton selectItemAtIndex:mSelectedTypeIndex];
192   [popupButton setTag:kSaveTypeControlTag];
193   [popupButton sizeToFit]; // we have to do sizeToFit to get the height calculated for us
194   // This is just a default width that works well, doesn't truncate the vast majority of
195   // things that might end up in the menu.
196   [popupButton setFrameSize:NSMakeSize(180, [popupButton frame].size.height)];
198   // position everything based on control sizes with kAccessoryViewPadding pix padding
199   // on each side kAccessoryViewPadding pix horizontal padding between controls
200   float greatestHeight = [textField frame].size.height;
201   if ([popupButton frame].size.height > greatestHeight)
202     greatestHeight = [popupButton frame].size.height;
203   float totalViewHeight = greatestHeight + kAccessoryViewPadding * 2;
204   float totalViewWidth  = [textField frame].size.width + [popupButton frame].size.width + kAccessoryViewPadding * 3;
205   [accessoryView setFrameSize:NSMakeSize(totalViewWidth, totalViewHeight)];
207   float textFieldOriginY = ((greatestHeight - [textField frame].size.height) / 2 + 1) + kAccessoryViewPadding;
208   [textField setFrameOrigin:NSMakePoint(kAccessoryViewPadding, textFieldOriginY)];
209   
210   float popupOriginX = [textField frame].size.width + kAccessoryViewPadding * 2;
211   float popupOriginY = ((greatestHeight - [popupButton frame].size.height) / 2) + kAccessoryViewPadding;
212   [popupButton setFrameOrigin:NSMakePoint(popupOriginX, popupOriginY)];
214   [accessoryView addSubview:textField];
215   [accessoryView addSubview:popupButton];
216   return accessoryView;
218   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
221 // Display the file dialog
222 NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval)
224   NS_ENSURE_ARG_POINTER(retval);
226   *retval = returnCancel;
228   PRInt16 userClicksOK = returnCancel;
230 // Random questions from DHH:
232 // Why do we pass mTitle, mDefault to the functions?  Can GetLocalFile. PutLocalFile,
233 // and GetLocalFolder get called someplace else?  It generates a bunch of warnings
234 // as it is right now.
236 // I think we could easily combine GetLocalFile and GetLocalFolder together, just
237 // setting panel pick options based on mMode.  I didn't do it here b/c I wanted to 
238 // make this look as much like Carbon nsFilePicker as possible.  
240   mFiles.Clear();
241   nsCOMPtr<nsILocalFile> theFile;
243   switch (mMode)
244   {
245     case modeOpen:
246       userClicksOK = GetLocalFiles(mTitle, mDefault, PR_FALSE, mFiles);
247       break;
248     
249     case modeOpenMultiple:
250       userClicksOK = GetLocalFiles(mTitle, mDefault, PR_TRUE, mFiles);
251       break;
252       
253     case modeSave:
254       userClicksOK = PutLocalFile(mTitle, mDefault, getter_AddRefs(theFile));
255       break;
256       
257     case modeGetFolder:
258       userClicksOK = GetLocalFolder(mTitle, getter_AddRefs(theFile));
259       break;
260     
261     default:
262       NS_ERROR("Unknown file picker mode");
263       break;
264   }
266   if (theFile)
267     mFiles.AppendObject(theFile);
268   
269   *retval = userClicksOK;
270   return NS_OK;
273 // Use OpenPanel to do a GetFile. Returns |returnOK| if the user presses OK in the dialog. 
274 PRInt16
275 nsFilePicker::GetLocalFiles(const nsString& inTitle, const nsString& inDefaultName, PRBool inAllowMultiple, nsCOMArray<nsILocalFile>& outFiles)
277   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
279   PRInt16 retVal = (PRInt16)returnCancel;
280   NSOpenPanel *thePanel = [NSOpenPanel openPanel];
282   SetShowHiddenFileState(thePanel);
284   // Get filters
285   // filters may be null, if we should allow all file types.
286   NSArray *filters = GenerateFilterList();
288   // Set the options for how the get file dialog will appear
289   SetDialogTitle(inTitle, thePanel);
290   [thePanel setAllowsMultipleSelection:inAllowMultiple];
291   [thePanel setCanSelectHiddenExtension:YES];
292   [thePanel setCanChooseDirectories:NO];
293   [thePanel setCanChooseFiles:YES];
294   [thePanel setResolvesAliases:YES];        //this is default - probably doesn't need to be set
295   
296   // if we show all file types, also "expose" bundles' contents.
297   if (!filters)
298     [thePanel setTreatsFilePackagesAsDirectories:NO];       
300   // set up default file name
301   NSString* defaultFilename = [NSString stringWithCharacters:(const unichar*)inDefaultName.get() length:inDefaultName.Length()];
303   // set up default directory
304   NSString *theDir = PanelDefaultDirectory();
305   
306   // if this is the "Choose application..." dialog, and no other start
307   // dir has been set, then use the Applications folder.
308   if (!theDir && filters && [filters count] == 1 && 
309       [(NSString *)[filters objectAtIndex:0] isEqualToString:@"app"]) {
310     theDir = @"/Applications/";
311   }
313   nsCocoaUtils::PrepareForNativeAppModalDialog();
314   int result = [thePanel runModalForDirectory:theDir file:defaultFilename
315                 types:filters];
316   nsCocoaUtils::CleanUpAfterNativeAppModalDialog();
317   
318   if (result == NSFileHandlingPanelCancelButton)
319     return retVal;
320   
321   // append each chosen file to our list
322   for (unsigned int i = 0; i < [[thePanel URLs] count]; i++) {
323     NSURL *theURL = [[thePanel URLs] objectAtIndex:i];
324     if (theURL) {
325       nsCOMPtr<nsILocalFile> localFile;
326       NS_NewLocalFile(EmptyString(), PR_TRUE, getter_AddRefs(localFile));
327       nsCOMPtr<nsILocalFileMac> macLocalFile = do_QueryInterface(localFile);
328       if (macLocalFile && NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)theURL)))
329         outFiles.AppendObject(localFile);
330     }
331   }
333   if (outFiles.Count() > 0)
334     retVal = returnOK;
336   return retVal;
338   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
341 // Use OpenPanel to do a GetFolder. Returns |returnOK| if the user presses OK in the dialog.
342 PRInt16
343 nsFilePicker::GetLocalFolder(const nsString& inTitle, nsILocalFile** outFile)
345   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
346   NS_ASSERTION(outFile, "this protected member function expects a null initialized out pointer");
347   
348   PRInt16 retVal = (PRInt16)returnCancel;
349   NSOpenPanel *thePanel = [NSOpenPanel openPanel];
351   SetShowHiddenFileState(thePanel);
353   // Set the options for how the get file dialog will appear
354   SetDialogTitle(inTitle, thePanel);
355   [thePanel setAllowsMultipleSelection:NO];   //this is default -probably doesn't need to be set
356   [thePanel setCanSelectHiddenExtension:YES];
357   [thePanel setCanChooseDirectories:YES];
358   [thePanel setCanChooseFiles:NO];
359   [thePanel setResolvesAliases:YES];          //this is default - probably doesn't need to be set
360   [thePanel setCanCreateDirectories:YES];
361   
362   // packages != folders
363   [thePanel setTreatsFilePackagesAsDirectories:NO];
365   // set up default directory
366   NSString *theDir = PanelDefaultDirectory();
367   nsCocoaUtils::PrepareForNativeAppModalDialog();
368   int result = [thePanel runModalForDirectory:theDir file:nil types:nil];  
369   nsCocoaUtils::CleanUpAfterNativeAppModalDialog();
371   if (result == NSFileHandlingPanelCancelButton)
372     return retVal;
374   // get the path for the folder (we allow just 1, so that's all we get)
375   NSURL *theURL = [[thePanel URLs] objectAtIndex:0];
376   if (theURL) {
377     nsCOMPtr<nsILocalFile> localFile;
378     NS_NewLocalFile(EmptyString(), PR_TRUE, getter_AddRefs(localFile));
379     nsCOMPtr<nsILocalFileMac> macLocalFile = do_QueryInterface(localFile);
380     if (macLocalFile && NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)theURL))) {
381       *outFile = localFile;
382       NS_ADDREF(*outFile);
383       retVal = returnOK;
384     }
385   }
387   return retVal;
389   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
392 // Returns |returnOK| if the user presses OK in the dialog.
393 PRInt16
394 nsFilePicker::PutLocalFile(const nsString& inTitle, const nsString& inDefaultName, nsILocalFile** outFile)
396   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
397   NS_ASSERTION(outFile, "this protected member function expects a null initialized out pointer");
399   PRInt16 retVal = returnCancel;
400   NSSavePanel *thePanel = [NSSavePanel savePanel];
402   SetShowHiddenFileState(thePanel);
404   SetDialogTitle(inTitle, thePanel);
406   // set up accessory view for file format options
407   NSView* accessoryView = GetAccessoryView();
408   [thePanel setAccessoryView:accessoryView];
410   // set up default file name
411   NSString* defaultFilename = [NSString stringWithCharacters:(const unichar*)inDefaultName.get() length:inDefaultName.Length()];
413   // set up default directory
414   NSString *theDir = PanelDefaultDirectory();
416   // load the panel
417   nsCocoaUtils::PrepareForNativeAppModalDialog();
418   int result = [thePanel runModalForDirectory:theDir file:defaultFilename];
419   nsCocoaUtils::CleanUpAfterNativeAppModalDialog();
420   if (result == NSFileHandlingPanelCancelButton)
421     return retVal;
423   // get the save type
424   NSPopUpButton* popupButton = [accessoryView viewWithTag:kSaveTypeControlTag];
425   if (popupButton) {
426     mSelectedTypeIndex = [popupButton indexOfSelectedItem];
427     // save out to prefs for initializing other file picker instances
428     nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
429     if (prefs)
430       prefs->SetIntPref(kLastTypeIndexPref, mSelectedTypeIndex);
431   }
433   NSURL* fileURL = [thePanel URL];
434   if (fileURL) { 
435     nsCOMPtr<nsILocalFile> localFile;
436     NS_NewLocalFile(EmptyString(), PR_TRUE, getter_AddRefs(localFile));
437     nsCOMPtr<nsILocalFileMac> macLocalFile = do_QueryInterface(localFile);
438     if (macLocalFile && NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)fileURL))) {
439       *outFile = localFile;
440       NS_ADDREF(*outFile);
441       // We tell if we are replacing or not by just looking to see if the file exists.
442       // The user could not have hit OK and not meant to replace the file.
443       if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]])
444         retVal = returnReplace;
445       else
446         retVal = returnOK;
447     }
448   }
450   return retVal;
452   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
455 // Take the list of file types (in a nice win32-specific format) and fills up
456 // an NSArray of them for the Open Panel.  Note: Will return nil if we should allow
457 // all file types.
458 NSArray *
459 nsFilePicker::GenerateFilterList()
461   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
463   NSArray *filterArray = nil;
464   if (mFilters.Length() > 0) {
465     // Set up our filter string
466     NSMutableString *giantFilterString = [[[NSMutableString alloc] initWithString:@""] autorelease];
468     // Loop through each of the filter strings
469     for (PRUint32 loop = 0; loop < mFilters.Length(); loop++) {
470       const nsString& filterWide = mFilters[loop];
472       // separate individual filters
473       if ([giantFilterString length] > 0)
474         [giantFilterString appendString:[NSString stringWithString:@";"]];
476       // handle special case filters
477       if (filterWide.Equals(NS_LITERAL_STRING("*"))) {
478         // if we'll allow all files, we won't bother parsing all other
479         // file types. just return early.
480         return nil;
481       }
482       else if (filterWide.Equals(NS_LITERAL_STRING("..apps"))) {
483         // this magic filter means that we should enable app bundles.
484         // translate it into a usable filter, and continue looping through 
485         // other filters.
486         [giantFilterString appendString:@"*.app"];
487         continue;
488       }
489       
490       if (filterWide.Length() > 0)
491         [giantFilterString appendString:[NSString stringWithCharacters:filterWide.get() length:filterWide.Length()]];
492     }
493     
494     // Now we clean stuff up.  Get rid of white spaces, "*"'s, and the odd period or two.
495     NSCharacterSet *aSet = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithString:@". *"]];
496     NSRange aRange = [giantFilterString rangeOfCharacterFromSet:aSet];
497     while (aRange.length) {
498       [giantFilterString replaceCharactersInRange:aRange withString:@""];
499       aRange = [giantFilterString rangeOfCharacterFromSet:aSet];
500     }   
501     // OK, if string isn't empty we'll make a new filter list
502     if ([giantFilterString length] > 0) {
503       // every time we find a semicolon, we've found a new filter.
504       // components SeparatedByString should do that for us.
505       filterArray = [[[NSArray alloc] initWithArray:[giantFilterString componentsSeparatedByString:@";"]] autorelease];
506     }
507   }
508   return filterArray;
510   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
513 // Sets the dialog title to whatever it should be.  If it fails, eh,
514 // the OS will provide a sensible default.
515 void
516 nsFilePicker::SetDialogTitle(const nsString& inTitle, id aPanel)
518   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
520   [aPanel setTitle:[NSString stringWithCharacters:(const unichar*)inTitle.get() length:inTitle.Length()]];
522   NS_OBJC_END_TRY_ABORT_BLOCK;
525 // Converts path from an nsILocalFile into a NSString path
526 // If it fails, returns an empty string.
527 NSString *
528 nsFilePicker::PanelDefaultDirectory()
530   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
532   NSString *directory = nil;
533   if (mDisplayDirectory) {
534     nsAutoString pathStr;
535     mDisplayDirectory->GetPath(pathStr);
536     directory = [[[NSString alloc] initWithCharacters:pathStr.get() length:pathStr.Length()] autorelease];
537   }
538   return directory;
540   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
543 NS_IMETHODIMP nsFilePicker::GetFile(nsILocalFile **aFile)
545   NS_ENSURE_ARG_POINTER(aFile);
546   *aFile = nsnull;
547   
548   // just return the first file
549   if (mFiles.Count() > 0) {
550     *aFile = mFiles.ObjectAt(0);
551     NS_IF_ADDREF(*aFile);
552   }
554   return NS_OK;
557 NS_IMETHODIMP nsFilePicker::GetFileURL(nsIURI **aFileURL)
559   NS_ENSURE_ARG_POINTER(aFileURL);
560   *aFileURL = nsnull;
562   if (mFiles.Count() == 0)
563     return NS_OK;
565   return NS_NewFileURI(aFileURL, mFiles.ObjectAt(0));
568 NS_IMETHODIMP nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
570   return NS_NewArrayEnumerator(aFiles, mFiles);
573 NS_IMETHODIMP nsFilePicker::SetDefaultString(const nsAString& aString)
575   mDefault = aString;
576   return NS_OK;
579 NS_IMETHODIMP nsFilePicker::GetDefaultString(nsAString& aString)
581   return NS_ERROR_FAILURE;
584 // The default extension to use for files
585 NS_IMETHODIMP nsFilePicker::GetDefaultExtension(nsAString& aExtension)
587   aExtension.Truncate();
588   return NS_OK;
591 NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const nsAString& aExtension)
593   return NS_OK;
596 // Append an entry to the filters array
597 NS_IMETHODIMP
598 nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
600   mFilters.AppendElement(aFilter);
601   mTitles.AppendElement(aTitle);
602   
603   return NS_OK;
606 // Get the filter index - do we still need this?
607 NS_IMETHODIMP nsFilePicker::GetFilterIndex(PRInt32 *aFilterIndex)
609   *aFilterIndex = mSelectedTypeIndex;
610   return NS_OK;
613 // Set the filter index - do we still need this?
614 NS_IMETHODIMP nsFilePicker::SetFilterIndex(PRInt32 aFilterIndex)
616   mSelectedTypeIndex = aFilterIndex;
617   return NS_OK;