mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
FileChoosers: Added a file-chooser save mode where the caller already supplies a temporary file which should be saved. JUCE will automatically move the temporary file to the location selected by the user
This commit is contained in:
parent
fd6b7de444
commit
df8fc9b910
8 changed files with 86 additions and 37 deletions
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue