| @@ -317,8 +317,16 @@ private: | |||
| } | |||
| else if (type == saveChooser) | |||
| { | |||
| File fileToSave = File::createTempFile ("saveChooserDemo"); | |||
| if (fileToSave.createDirectory().wasOk()) | |||
| { | |||
| fileToSave = fileToSave.getChildFile ("JUCE.png"); | |||
| fileToSave.replaceWithData (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize); | |||
| } | |||
| fc = new FileChooser ("Choose a file to save...", | |||
| File::getCurrentWorkingDirectory(), | |||
| File::getCurrentWorkingDirectory().getChildFile (fileToSave.getFileName()), | |||
| "*", | |||
| useNativeVersion); | |||
| @@ -333,7 +341,7 @@ private: | |||
| AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, | |||
| "File Chooser...", | |||
| "You picked: " + name); | |||
| }); | |||
| }, nullptr, fileToSave); | |||
| } | |||
| else if (type == directoryChooser) | |||
| { | |||
| @@ -73,7 +73,7 @@ private: | |||
| result.add (URL (browserComponent.getSelectedFile (i))); | |||
| } | |||
| owner.finished (result); | |||
| owner.finished (result, true); | |||
| } | |||
| //============================================================================== | |||
| @@ -137,12 +137,13 @@ bool FileChooser::browseForMultipleFilesOrDirectories (FilePreviewComponent* pre | |||
| previewComp); | |||
| } | |||
| bool FileChooser::browseForFileToSave (const bool warnAboutOverwrite) | |||
| bool FileChooser::browseForFileToSave (const bool warnAboutOverwrite, | |||
| const File& fileWhichShouldBeSaved) | |||
| { | |||
| return showDialog (FileBrowserComponent::saveMode | |||
| | FileBrowserComponent::canSelectFiles | |||
| | (warnAboutOverwrite ? FileBrowserComponent::warnAboutOverwriting : 0), | |||
| nullptr); | |||
| nullptr, fileWhichShouldBeSaved); | |||
| } | |||
| bool FileChooser::browseForDirectory() | |||
| @@ -152,8 +153,11 @@ bool FileChooser::browseForDirectory() | |||
| nullptr); | |||
| } | |||
| bool FileChooser::showDialog (const int flags, FilePreviewComponent* const previewComp) | |||
| bool FileChooser::showDialog (const int flags, FilePreviewComponent* const previewComp, | |||
| const File& fileWhichShouldBeSaved) | |||
| { | |||
| fileToSave = (flags & FileBrowserComponent::saveMode) != 0 ? fileWhichShouldBeSaved : File(); | |||
| FocusRestorer focusRestorer; | |||
| pimpl = createPimpl (flags, previewComp); | |||
| @@ -167,7 +171,8 @@ bool FileChooser::showDialog (const int flags, FilePreviewComponent* const previ | |||
| #endif | |||
| void FileChooser::launchAsync (int flags, std::function<void (const FileChooser&)> callback, | |||
| FilePreviewComponent* previewComp) | |||
| FilePreviewComponent* previewComp, | |||
| const File& fileWhichShouldBeSaved) | |||
| { | |||
| // You must specify a callback when using launchAsync | |||
| jassert (callback); | |||
| @@ -175,6 +180,8 @@ void FileChooser::launchAsync (int flags, std::function<void (const FileChooser& | |||
| // you cannot run two file chooser dialog boxes at the same time | |||
| jassert (asyncCallback == nullptr); | |||
| fileToSave = (flags & FileBrowserComponent::saveMode) != 0 ? fileWhichShouldBeSaved : File(); | |||
| asyncCallback = static_cast<std::function<void (const FileChooser&)>&&> (callback); | |||
| pimpl = createPimpl (flags, previewComp); | |||
| @@ -249,13 +256,23 @@ URL FileChooser::getURLResult() const | |||
| return results.getFirst(); | |||
| } | |||
| void FileChooser::finished (const Array<URL>& asyncResults) | |||
| void FileChooser::finished (const Array<URL>& asyncResults, bool shouldMove) | |||
| { | |||
| std::function<void (const FileChooser&)> callback; | |||
| std::swap (callback, asyncCallback); | |||
| results = asyncResults; | |||
| if (shouldMove && fileToSave.existsAsFile() && results.size() > 0) | |||
| { | |||
| // The user either selected multiple files or wants to save the file to a URL | |||
| // Both are not supported | |||
| jassert (results.size() == 1 && results.getReference (0).isLocalFile()); | |||
| if (! fileToSave.moveFileTo (results.getReference (0).getLocalFile())) | |||
| results.clear(); | |||
| } | |||
| pimpl = nullptr; | |||
| if (callback) | |||
| @@ -66,7 +66,8 @@ public: | |||
| @param initialFileOrDirectory the file or directory that should be selected | |||
| when the dialog box opens. If this parameter is | |||
| set to File(), a sensible default directory will | |||
| be used instead. | |||
| be used instead. This parameter is ignored for native | |||
| iOS file choosers. | |||
| @param filePatternsAllowed a set of file patterns to specify which files | |||
| can be selected - each pattern should be | |||
| separated by a comma or semi-colon, e.g. "*" or | |||
| @@ -122,12 +123,22 @@ public: | |||
| @param warnAboutOverwritingExistingFiles if true, the dialog box will ask | |||
| the user if they're sure they want to overwrite a file that already | |||
| exists | |||
| @param fileWhichShouldBeSaved if this parameter is specified, then, if the the user | |||
| selects a valid location to save the file, fileWhichShouldBeSaved will | |||
| automaitcally be moved to the location selected by the user when the user | |||
| clicks 'ok'. If you do not specify this parameter, then it is your | |||
| responsibility to save your file at the location that is returned from this | |||
| file chooser. Typically, when using this parameter, you already write the | |||
| file you wish to save to a temporary location and then supply the path to | |||
| this file to this parameter. This parameter is required on iOS when using | |||
| native file save dialogs but can be used on all other platforms. | |||
| @returns true if the user chose a file and pressed 'ok', in which case, use | |||
| the getResult() method to find out what the file was. Returns false | |||
| if they cancelled instead. | |||
| @see browseForFileToOpen, browseForDirectory | |||
| */ | |||
| bool browseForFileToSave (bool warnAboutOverwritingExistingFiles); | |||
| bool browseForFileToSave (bool warnAboutOverwritingExistingFiles, | |||
| const File& fileWhichShouldBeSaved = File()); | |||
| /** Shows a dialog box to choose a directory. | |||
| @@ -152,12 +163,24 @@ public: | |||
| /** Runs a dialog box for the given set of option flags. | |||
| The flag values used are those in FileBrowserComponent::FileChooserFlags. | |||
| @param fileWhichShouldBeSaved if this parameter is specified and saveMode is | |||
| specified, then, if the the user selects a valid location to save the file, | |||
| fileWhichShouldBeSaved will automaitcally be moved to the location selected | |||
| by the user when the user clicks 'ok'. If you do not specify this parameter, | |||
| then it is your responsibility to save your file at the location that is | |||
| returned from this file chooser. Typically, when using this parameter, | |||
| you already write the file you wish to save to a temporary location and | |||
| then supply the path to this file to this parameter. This parameter is | |||
| required on iOS when using native file save dialogs but can be used on all | |||
| other platforms. | |||
| @returns true if the user chose a directory and pressed 'ok', in which case, use | |||
| the getResult() method to find out what they chose. Returns false | |||
| if they cancelled instead. | |||
| @see FileBrowserComponent::FileChooserFlags | |||
| */ | |||
| bool showDialog (int flags, FilePreviewComponent* previewComponent); | |||
| bool showDialog (int flags, FilePreviewComponent* previewComponent, | |||
| const File& fileWhichShouldBeSaved = File()); | |||
| /** Use this method to launch the file browser window asynchronously. | |||
| @@ -173,10 +196,22 @@ public: | |||
| You must ensure that the lifetime of the callback object is longer than | |||
| the lifetime of the file-chooser. | |||
| @param fileWhichShouldBeSaved if this parameter is specified and saveMode is | |||
| specified, then, if the the user selects a valid location to save the file, | |||
| fileWhichShouldBeSaved will automaitcally be moved to the location selected | |||
| by the user when the user clicks 'ok'. If you do not specify this parameter, | |||
| then it is your responsibility to save your file at the location that is | |||
| returned from this file chooser. Typically, when using this parameter, | |||
| you already write the file you wish to save to a temporary location and | |||
| then supply the path to this file to this parameter. This parameter is | |||
| required on iOS when using native file save dialogs but can be used on all | |||
| other platforms. | |||
| */ | |||
| void launchAsync (int flags, | |||
| std::function<void (const FileChooser&)>, | |||
| FilePreviewComponent* previewComponent = nullptr); | |||
| FilePreviewComponent* previewComponent = nullptr, | |||
| const File& fileWhichShouldBeSaved = File()); | |||
| //============================================================================== | |||
| /** Returns the last file that was chosen by one of the browseFor methods. | |||
| @@ -253,14 +288,14 @@ public: | |||
| private: | |||
| //============================================================================== | |||
| String title, filters; | |||
| const File startingFile; | |||
| File startingFile, fileToSave; | |||
| Array<URL> results; | |||
| const bool useNativeDialogBox; | |||
| const bool treatFilePackagesAsDirs; | |||
| std::function<void (const FileChooser&)> asyncCallback; | |||
| //============================================================================== | |||
| void finished (const Array<URL>&); | |||
| void finished (const Array<URL>&, bool); | |||
| //============================================================================== | |||
| struct Pimpl | |||
| @@ -168,7 +168,7 @@ public: | |||
| } | |||
| } | |||
| owner.finished (chosenURLs); | |||
| owner.finished (chosenURLs, true); | |||
| } | |||
| static Native* currentFileChooser; | |||
| @@ -45,25 +45,14 @@ public: | |||
| if ((flags & FileBrowserComponent::saveMode) != 0) | |||
| { | |||
| auto currentFileOrDirectory = owner.startingFile; | |||
| // You must specify the fileWhichShouldBeSaved parameter when using | |||
| // the native save dialog on iOS! | |||
| jassert (owner.fileToSave.existsAsFile()); | |||
| if (! currentFileOrDirectory.existsAsFile()) | |||
| { | |||
| auto filename = (currentFileOrDirectory.isDirectory() ? "Untitled" : currentFileOrDirectory.getFileName()); | |||
| auto tmpDirectory = File::createTempFile ("iosDummyFiles"); | |||
| if (tmpDirectory.createDirectory().wasOk()) | |||
| { | |||
| currentFileOrDirectory = tmpDirectory.getChildFile (filename); | |||
| currentFileOrDirectory.replaceWithText (""); | |||
| } | |||
| } | |||
| auto url = [[NSURL alloc] initFileURLWithPath:juceStringToNS (currentFileOrDirectory.getFullPathName())]; | |||
| auto url = [[NSURL alloc] initFileURLWithPath:juceStringToNS (owner.fileToSave.getFullPathName())]; | |||
| controller = [[UIDocumentPickerViewController alloc] initWithURL:url | |||
| inMode:UIDocumentPickerModeMoveToService]; | |||
| inMode:UIDocumentPickerModeExportToService]; | |||
| [url release]; | |||
| } | |||
| else | |||
| @@ -158,7 +147,7 @@ private: | |||
| Array<URL> chooserResults; | |||
| chooserResults.add (URL (nsStringToJuce ([url absoluteString]))); | |||
| owner.finished (chooserResults); | |||
| owner.finished (chooserResults, false); | |||
| exitModalState (1); | |||
| } | |||
| @@ -166,7 +155,7 @@ private: | |||
| { | |||
| Array<URL> chooserResults; | |||
| owner.finished (chooserResults); | |||
| owner.finished (chooserResults, false); | |||
| exitModalState (0); | |||
| } | |||
| @@ -122,7 +122,7 @@ private: | |||
| if (! shouldKill) | |||
| { | |||
| child.waitForProcessToFinish (60 * 1000); | |||
| owner.finished (selection); | |||
| owner.finished (selection, true); | |||
| } | |||
| } | |||
| @@ -213,7 +213,7 @@ private: | |||
| } | |||
| } | |||
| owner.finished (chooserResults); | |||
| owner.finished (chooserResults, true); | |||
| } | |||
| bool shouldShowFilename (const String& filenameToTest) | |||
| @@ -535,7 +535,7 @@ public: | |||
| [safeThis] (int) | |||
| { | |||
| if (safeThis != nullptr) | |||
| safeThis->owner.finished (safeThis->nativeFileChooser->results); | |||
| safeThis->owner.finished (safeThis->nativeFileChooser->results, true); | |||
| })); | |||
| nativeFileChooser->open (true); | |||
| @@ -548,7 +548,7 @@ public: | |||
| exitModalState (nativeFileChooser->results.size() > 0 ? 1 : 0); | |||
| nativeFileChooser->cancel(); | |||
| owner.finished (nativeFileChooser->results); | |||
| owner.finished (nativeFileChooser->results, true); | |||
| } | |||
| private: | |||