Browse Source

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

tags/2021-05-28
hogliux 8 years ago
parent
commit
df8fc9b910
8 changed files with 86 additions and 37 deletions
  1. +10
    -2
      examples/Demo/Source/Demos/DialogsDemo.cpp
  2. +23
    -6
      modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp
  3. +41
    -6
      modules/juce_gui_basics/filebrowser/juce_FileChooser.h
  4. +1
    -1
      modules/juce_gui_basics/native/juce_android_FileChooser.cpp
  5. +7
    -18
      modules/juce_gui_basics/native/juce_ios_FileChooser.mm
  6. +1
    -1
      modules/juce_gui_basics/native/juce_linux_FileChooser.cpp
  7. +1
    -1
      modules/juce_gui_basics/native/juce_mac_FileChooser.mm
  8. +2
    -2
      modules/juce_gui_basics/native/juce_win32_FileChooser.cpp

+ 10
- 2
examples/Demo/Source/Demos/DialogsDemo.cpp View File

@@ -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)
{


+ 23
- 6
modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp View File

@@ -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)


+ 41
- 6
modules/juce_gui_basics/filebrowser/juce_FileChooser.h View File

@@ -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


+ 1
- 1
modules/juce_gui_basics/native/juce_android_FileChooser.cpp View File

@@ -168,7 +168,7 @@ public:
}
}
owner.finished (chosenURLs);
owner.finished (chosenURLs, true);
}
static Native* currentFileChooser;


+ 7
- 18
modules/juce_gui_basics/native/juce_ios_FileChooser.mm View File

@@ -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);
}


+ 1
- 1
modules/juce_gui_basics/native/juce_linux_FileChooser.cpp View File

@@ -122,7 +122,7 @@ private:
if (! shouldKill)
{
child.waitForProcessToFinish (60 * 1000);
owner.finished (selection);
owner.finished (selection, true);
}
}


+ 1
- 1
modules/juce_gui_basics/native/juce_mac_FileChooser.mm View File

@@ -213,7 +213,7 @@ private:
}
}
owner.finished (chooserResults);
owner.finished (chooserResults, true);
}
bool shouldShowFilename (const String& filenameToTest)


+ 2
- 2
modules/juce_gui_basics/native/juce_win32_FileChooser.cpp View File

@@ -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…
Cancel
Save