mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-31 03:00:05 +00:00
Added multiple-selection, and the ability to browse for both files and folders to the Juce file chooser dialog classes. This has involved changing a few methods, so if you're using these classes directly, you may need to tweak your code, but it should be very easy to do.
This commit is contained in:
parent
71a12a140e
commit
1f6d9ec92c
13 changed files with 602 additions and 307 deletions
|
|
@ -3911,6 +3911,27 @@ DynamicObject* var::getObject() const throw()
|
|||
return type == objectType ? value.objectValue : 0;
|
||||
}
|
||||
|
||||
bool var::operator== (const var& other) const throw()
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case voidType: return other.isVoid();
|
||||
case intType: return value.intValue == (int) other;
|
||||
case boolType: return value.boolValue == (bool) other;
|
||||
case doubleType: return value.doubleValue == (double) other;
|
||||
case stringType: return (*(value.stringValue)) == other.toString();
|
||||
case objectType: return value.objectValue == other.getObject();
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool var::operator!= (const var& other) const throw()
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
const var var::operator[] (const var::identifier& propertyName) const throw()
|
||||
{
|
||||
if (type == objectType && value.objectValue != 0)
|
||||
|
|
@ -15311,7 +15332,7 @@ const String XmlElement::getText() const throw()
|
|||
{
|
||||
jassert (isTextElement()); // you're trying to get the text from an element that
|
||||
// isn't actually a text element.. If this contains text sub-nodes, you
|
||||
// can use getAllSubText instead to
|
||||
// probably want to use getAllSubText instead.
|
||||
|
||||
return getStringAttribute (juce_xmltextContentAttributeName);
|
||||
}
|
||||
|
|
@ -45460,14 +45481,14 @@ namespace CppTokeniser
|
|||
static bool isIdentifierStart (const tchar c) throw()
|
||||
{
|
||||
return CharacterFunctions::isLetter (c)
|
||||
|| c == T('_');
|
||||
|| c == T('_') || c == T('@');
|
||||
}
|
||||
|
||||
static bool isIdentifierBody (const tchar c) throw()
|
||||
{
|
||||
return CharacterFunctions::isLetter (c)
|
||||
|| CharacterFunctions::isDigit (c)
|
||||
|| c == T('_');
|
||||
|| c == T('_') || c == T('@');
|
||||
}
|
||||
|
||||
static int parseIdentifier (CodeDocument::Iterator& source) throw()
|
||||
|
|
@ -45494,7 +45515,9 @@ static int parseIdentifier (CodeDocument::Iterator& source) throw()
|
|||
static const tchar* keywordsOther[] =
|
||||
{ T("const_cast"), T("continue"), T("default"), T("explicit"), T("mutable"), T("namespace"),
|
||||
T("operator"), T("private"), T("protected"), T("register"), T("reinterpret_cast"), T("static_cast"),
|
||||
T("template"), T("typedef"), T("typename"), T("unsigned"), T("virtual"), T("volatile"), 0 };
|
||||
T("template"), T("typedef"), T("typename"), T("unsigned"), T("virtual"), T("volatile"),
|
||||
T("@implementation"), T("@interface"), T("@end"), T("@synthesize"), T("@dynamic"), T("@public"),
|
||||
T("@private"), T("@property"), T("@protected"), T("@class"), 0 };
|
||||
|
||||
int tokenLength = 0;
|
||||
tchar possibleIdentifier [19];
|
||||
|
|
@ -56413,27 +56436,24 @@ END_JUCE_NAMESPACE
|
|||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
class DirectoriesOnlyFilter : public FileFilter
|
||||
{
|
||||
public:
|
||||
DirectoriesOnlyFilter() : FileFilter (String::empty) {}
|
||||
|
||||
bool isFileSuitable (const File&) const { return false; }
|
||||
bool isDirectorySuitable (const File&) const { return true; }
|
||||
};
|
||||
|
||||
FileBrowserComponent::FileBrowserComponent (FileChooserMode mode_,
|
||||
FileBrowserComponent::FileBrowserComponent (int flags_,
|
||||
const File& initialFileOrDirectory,
|
||||
const FileFilter* fileFilter,
|
||||
FilePreviewComponent* previewComp_,
|
||||
const bool useTreeView,
|
||||
const bool filenameTextBoxIsReadOnly)
|
||||
: directoriesOnlyFilter (0),
|
||||
mode (mode_),
|
||||
const FileFilter* fileFilter_,
|
||||
FilePreviewComponent* previewComp_)
|
||||
: FileFilter (String::empty),
|
||||
fileFilter (fileFilter_),
|
||||
flags (flags_),
|
||||
listeners (2),
|
||||
previewComp (previewComp_),
|
||||
thread ("Juce FileBrowser")
|
||||
{
|
||||
// You need to specify one or other of the open/save flags..
|
||||
jassert ((flags & (saveMode | openMode)) != 0);
|
||||
jassert ((flags & (saveMode | openMode)) != (saveMode | openMode));
|
||||
|
||||
// You need to specify at least one of these flags..
|
||||
jassert ((flags & (canSelectFiles | canSelectDirectories)) != 0);
|
||||
|
||||
String filename;
|
||||
|
||||
if (initialFileOrDirectory == File::nonexistent)
|
||||
|
|
@ -56446,18 +56466,20 @@ FileBrowserComponent::FileBrowserComponent (FileChooserMode mode_,
|
|||
}
|
||||
else
|
||||
{
|
||||
chosenFiles.add (new File (initialFileOrDirectory));
|
||||
currentRoot = initialFileOrDirectory.getParentDirectory();
|
||||
filename = initialFileOrDirectory.getFileName();
|
||||
}
|
||||
|
||||
if (mode_ == chooseDirectoryMode)
|
||||
fileFilter = directoriesOnlyFilter = new DirectoriesOnlyFilter();
|
||||
fileList = new DirectoryContentsList (this, thread);
|
||||
|
||||
fileList = new DirectoryContentsList (fileFilter, thread);
|
||||
|
||||
if (useTreeView)
|
||||
if ((flags & useTreeView) != 0)
|
||||
{
|
||||
FileTreeComponent* const tree = new FileTreeComponent (*fileList);
|
||||
|
||||
if ((flags & canSelectMultipleItems) != 0)
|
||||
tree->setMultiSelectEnabled (true);
|
||||
|
||||
addAndMakeVisible (tree);
|
||||
fileListComponent = tree;
|
||||
}
|
||||
|
|
@ -56465,6 +56487,10 @@ FileBrowserComponent::FileBrowserComponent (FileChooserMode mode_,
|
|||
{
|
||||
FileListComponent* const list = new FileListComponent (*fileList);
|
||||
list->setOutlineThickness (1);
|
||||
|
||||
if ((flags & canSelectMultipleItems) != 0)
|
||||
list->setMultipleSelectionEnabled (true);
|
||||
|
||||
addAndMakeVisible (list);
|
||||
fileListComponent = list;
|
||||
}
|
||||
|
|
@ -56492,11 +56518,11 @@ FileBrowserComponent::FileBrowserComponent (FileChooserMode mode_,
|
|||
filenameBox->setMultiLine (false);
|
||||
filenameBox->setSelectAllWhenFocused (true);
|
||||
filenameBox->setText (filename, false);
|
||||
filenameBox->addListener (this);
|
||||
filenameBox->setReadOnly (filenameTextBoxIsReadOnly);
|
||||
|
||||
Label* label = new Label ("f", (mode == chooseDirectoryMode) ? TRANS("folder:")
|
||||
: TRANS("file:"));
|
||||
filenameBox->addListener (this);
|
||||
filenameBox->setReadOnly ((flags & (filenameBoxIsReadOnly | canSelectMultipleItems)) != 0);
|
||||
|
||||
Label* label = new Label ("f", TRANS("file:"));
|
||||
addAndMakeVisible (label);
|
||||
label->attachToComponent (filenameBox, true);
|
||||
|
||||
|
|
@ -56519,10 +56545,7 @@ FileBrowserComponent::~FileBrowserComponent()
|
|||
removeChildComponent (previewComp);
|
||||
|
||||
deleteAllChildren();
|
||||
|
||||
deleteAndZero (fileList);
|
||||
delete directoriesOnlyFilter;
|
||||
|
||||
thread.stopThread (10000);
|
||||
}
|
||||
|
||||
|
|
@ -56539,19 +56562,33 @@ void FileBrowserComponent::removeListener (FileBrowserListener* const listener)
|
|||
listeners.removeValue (listener);
|
||||
}
|
||||
|
||||
const File FileBrowserComponent::getCurrentFile() const throw()
|
||||
bool FileBrowserComponent::isSaveMode() const throw()
|
||||
{
|
||||
return currentRoot.getChildFile (filenameBox->getText());
|
||||
return (flags & saveMode) != 0;
|
||||
}
|
||||
|
||||
int FileBrowserComponent::getNumSelectedFiles() const throw()
|
||||
{
|
||||
if (chosenFiles.size() == 0 && currentFileIsValid())
|
||||
return 1;
|
||||
|
||||
return chosenFiles.size();
|
||||
}
|
||||
|
||||
const File FileBrowserComponent::getSelectedFile (int index) const throw()
|
||||
{
|
||||
if (! filenameBox->isReadOnly())
|
||||
return currentRoot.getChildFile (filenameBox->getText());
|
||||
else
|
||||
return chosenFiles[index] != 0 ? *chosenFiles[index] : File::nonexistent;
|
||||
}
|
||||
|
||||
bool FileBrowserComponent::currentFileIsValid() const
|
||||
{
|
||||
if (mode == saveFileMode)
|
||||
return ! getCurrentFile().isDirectory();
|
||||
else if (mode == loadFileMode)
|
||||
return getCurrentFile().existsAsFile();
|
||||
else if (mode == chooseDirectoryMode)
|
||||
return getCurrentFile().isDirectory();
|
||||
if (isSaveMode())
|
||||
return ! getSelectedFile (0).isDirectory();
|
||||
else
|
||||
return getSelectedFile (0).exists();
|
||||
|
||||
jassertfalse
|
||||
return false;
|
||||
|
|
@ -56559,7 +56596,27 @@ bool FileBrowserComponent::currentFileIsValid() const
|
|||
|
||||
const File FileBrowserComponent::getHighlightedFile() const throw()
|
||||
{
|
||||
return fileListComponent->getSelectedFile();
|
||||
return fileListComponent->getSelectedFile (0);
|
||||
}
|
||||
|
||||
bool FileBrowserComponent::isFileSuitable (const File& file) const
|
||||
{
|
||||
return (flags & canSelectFiles) != 0 ? (fileFilter == 0 || fileFilter->isFileSuitable (file))
|
||||
: false;
|
||||
}
|
||||
|
||||
bool FileBrowserComponent::isDirectorySuitable (const File&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileBrowserComponent::isFileOrDirSuitable (const File& f) const
|
||||
{
|
||||
if (f.isDirectory())
|
||||
return (flags & canSelectDirectories) != 0 && (fileFilter == 0 || fileFilter->isDirectorySuitable (f));
|
||||
|
||||
return (flags & canSelectFiles) != 0 && f.exists()
|
||||
&& (fileFilter == 0 || fileFilter->isFileSuitable (f));
|
||||
}
|
||||
|
||||
const File FileBrowserComponent::getRoot() const
|
||||
|
|
@ -56573,9 +56630,6 @@ void FileBrowserComponent::setRoot (const File& newRootDirectory)
|
|||
{
|
||||
fileListComponent->scrollToTop();
|
||||
|
||||
if (mode == chooseDirectoryMode)
|
||||
filenameBox->setText (String::empty, false);
|
||||
|
||||
String path (newRootDirectory.getFullPathName());
|
||||
|
||||
if (path.isEmpty())
|
||||
|
|
@ -56627,8 +56681,7 @@ void FileBrowserComponent::refresh()
|
|||
|
||||
const String FileBrowserComponent::getActionVerb() const
|
||||
{
|
||||
return (mode == chooseDirectoryMode) ? TRANS("Choose")
|
||||
: ((mode == saveFileMode) ? TRANS("Save") : TRANS("Open"));
|
||||
return isSaveMode() ? TRANS("Save") : TRANS("Open");
|
||||
}
|
||||
|
||||
FilePreviewComponent* FileBrowserComponent::getPreviewComponent() const throw()
|
||||
|
|
@ -56649,7 +56702,7 @@ void FileBrowserComponent::sendListenerChangeMessage()
|
|||
ComponentDeletionWatcher deletionWatcher (this);
|
||||
|
||||
if (previewComp != 0)
|
||||
previewComp->selectedFileChanged (getCurrentFile());
|
||||
previewComp->selectedFileChanged (getSelectedFile (0));
|
||||
|
||||
jassert (! deletionWatcher.hasBeenDeleted());
|
||||
|
||||
|
|
@ -56666,14 +56719,29 @@ void FileBrowserComponent::sendListenerChangeMessage()
|
|||
|
||||
void FileBrowserComponent::selectionChanged()
|
||||
{
|
||||
const File selected (fileListComponent->getSelectedFile());
|
||||
StringArray newFilenames;
|
||||
bool resetChosenFiles = true;
|
||||
|
||||
if ((mode == chooseDirectoryMode && selected.isDirectory())
|
||||
|| selected.existsAsFile())
|
||||
for (int i = 0; i < fileListComponent->getNumSelectedFiles(); ++i)
|
||||
{
|
||||
filenameBox->setText (selected.getRelativePathFrom (getRoot()), false);
|
||||
const File f (fileListComponent->getSelectedFile (i));
|
||||
|
||||
if (isFileOrDirSuitable (f))
|
||||
{
|
||||
if (resetChosenFiles)
|
||||
{
|
||||
chosenFiles.clear();
|
||||
resetChosenFiles = false;
|
||||
}
|
||||
|
||||
chosenFiles.add (new File (f));
|
||||
newFilenames.add (f.getRelativePathFrom (getRoot()));
|
||||
}
|
||||
}
|
||||
|
||||
if (newFilenames.size() > 0)
|
||||
filenameBox->setText (newFilenames.joinIntoString (T(", ")), false);
|
||||
|
||||
sendListenerChangeMessage();
|
||||
}
|
||||
|
||||
|
|
@ -56743,17 +56811,20 @@ void FileBrowserComponent::textEditorReturnKeyPressed (TextEditor&)
|
|||
if (f.isDirectory())
|
||||
{
|
||||
setRoot (f);
|
||||
chosenFiles.clear();
|
||||
filenameBox->setText (String::empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
setRoot (f.getParentDirectory());
|
||||
chosenFiles.clear();
|
||||
chosenFiles.add (new File (f));
|
||||
filenameBox->setText (f.getFileName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fileDoubleClicked (getCurrentFile());
|
||||
fileDoubleClicked (getSelectedFile (0));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -56763,7 +56834,7 @@ void FileBrowserComponent::textEditorEscapeKeyPressed (TextEditor&)
|
|||
|
||||
void FileBrowserComponent::textEditorFocusLost (TextEditor&)
|
||||
{
|
||||
if (mode != saveFileMode)
|
||||
if (! isSaveMode())
|
||||
selectionChanged();
|
||||
}
|
||||
|
||||
|
|
@ -56917,22 +56988,27 @@ FileChooser::~FileChooser()
|
|||
|
||||
bool FileChooser::browseForFileToOpen (FilePreviewComponent* previewComponent)
|
||||
{
|
||||
return showDialog (false, false, false, false, previewComponent);
|
||||
return showDialog (false, true, false, false, false, previewComponent);
|
||||
}
|
||||
|
||||
bool FileChooser::browseForMultipleFilesToOpen (FilePreviewComponent* previewComponent)
|
||||
{
|
||||
return showDialog (false, false, false, true, previewComponent);
|
||||
return showDialog (false, true, false, false, true, previewComponent);
|
||||
}
|
||||
|
||||
bool FileChooser::browseForMultipleFilesOrDirectories (FilePreviewComponent* previewComponent)
|
||||
{
|
||||
return showDialog (true, true, false, false, true, previewComponent);
|
||||
}
|
||||
|
||||
bool FileChooser::browseForFileToSave (const bool warnAboutOverwritingExistingFiles)
|
||||
{
|
||||
return showDialog (false, true, warnAboutOverwritingExistingFiles, false, 0);
|
||||
return showDialog (false, true, true, warnAboutOverwritingExistingFiles, false, 0);
|
||||
}
|
||||
|
||||
bool FileChooser::browseForDirectory()
|
||||
{
|
||||
return showDialog (true, false, false, false, 0);
|
||||
return showDialog (true, false, false, false, false, 0);
|
||||
}
|
||||
|
||||
const File FileChooser::getResult() const
|
||||
|
|
@ -56954,7 +57030,8 @@ const OwnedArray <File>& FileChooser::getResults() const
|
|||
return results;
|
||||
}
|
||||
|
||||
bool FileChooser::showDialog (const bool isDirectory,
|
||||
bool FileChooser::showDialog (const bool selectsDirectories,
|
||||
const bool selectsFiles,
|
||||
const bool isSave,
|
||||
const bool warnAboutOverwritingExistingFiles,
|
||||
const bool selectMultipleFiles,
|
||||
|
|
@ -56973,27 +57050,38 @@ bool FileChooser::showDialog (const bool isDirectory,
|
|||
&& previewComponent->getHeight() > 10));
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
if (useNativeDialogBox)
|
||||
#else
|
||||
if (useNativeDialogBox && ! (selectsFiles && selectsDirectories))
|
||||
#elif JUCE_MAC
|
||||
if (useNativeDialogBox && (previewComponent == 0))
|
||||
#else
|
||||
if (false)
|
||||
#endif
|
||||
{
|
||||
showPlatformDialog (results, title, startingFile, filters,
|
||||
isDirectory, isSave,
|
||||
selectsDirectories, selectsFiles, isSave,
|
||||
warnAboutOverwritingExistingFiles,
|
||||
selectMultipleFiles,
|
||||
previewComponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
jassert (! selectMultipleFiles); // not yet implemented for juce dialogs!
|
||||
WildcardFileFilter wildcard (selectsFiles ? filters : String::empty,
|
||||
selectsDirectories ? "*" : String::empty,
|
||||
String::empty);
|
||||
|
||||
WildcardFileFilter wildcard (filters, String::empty);
|
||||
int flags = isSave ? FileBrowserComponent::saveMode
|
||||
: FileBrowserComponent::openMode;
|
||||
|
||||
FileBrowserComponent browserComponent (isDirectory ? FileBrowserComponent::chooseDirectoryMode
|
||||
: (isSave ? FileBrowserComponent::saveFileMode
|
||||
: FileBrowserComponent::loadFileMode),
|
||||
startingFile, &wildcard, previewComponent);
|
||||
if (selectsFiles)
|
||||
flags |= FileBrowserComponent::canSelectFiles;
|
||||
|
||||
if (selectsDirectories)
|
||||
flags |= FileBrowserComponent::canSelectDirectories;
|
||||
|
||||
if (selectMultipleFiles)
|
||||
flags |= FileBrowserComponent::canSelectMultipleItems;
|
||||
|
||||
FileBrowserComponent browserComponent (flags, startingFile, &wildcard, previewComponent);
|
||||
|
||||
FileChooserDialogBox box (title, String::empty,
|
||||
browserComponent,
|
||||
|
|
@ -57001,7 +57089,10 @@ bool FileChooser::showDialog (const bool isDirectory,
|
|||
browserComponent.findColour (AlertWindow::backgroundColourId));
|
||||
|
||||
if (box.show())
|
||||
results.add (new File (browserComponent.getCurrentFile()));
|
||||
{
|
||||
for (int i = 0; i < browserComponent.getNumSelectedFiles(); ++i)
|
||||
results.add (new File (browserComponent.getSelectedFile (i)));
|
||||
}
|
||||
}
|
||||
|
||||
if (currentlyFocused != 0 && ! currentlyFocusedChecker->hasBeenDeleted())
|
||||
|
|
@ -57092,13 +57183,13 @@ void FileChooserDialogBox::buttonClicked (Button* button)
|
|||
if (button == content->okButton)
|
||||
{
|
||||
if (warnAboutOverwritingExistingFiles
|
||||
&& content->chooserComponent->getMode() == FileBrowserComponent::saveFileMode
|
||||
&& content->chooserComponent->getCurrentFile().exists())
|
||||
&& content->chooserComponent->isSaveMode()
|
||||
&& content->chooserComponent->getSelectedFile(0).exists())
|
||||
{
|
||||
if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
|
||||
TRANS("File already exists"),
|
||||
TRANS("There's already a file called:\n\n")
|
||||
+ content->chooserComponent->getCurrentFile().getFullPathName()
|
||||
+ content->chooserComponent->getSelectedFile(0).getFullPathName()
|
||||
+ T("\n\nAre you sure you want to overwrite it?"),
|
||||
TRANS("overwrite"),
|
||||
TRANS("cancel")))
|
||||
|
|
@ -57214,9 +57305,14 @@ FileListComponent::~FileListComponent()
|
|||
deleteAllChildren();
|
||||
}
|
||||
|
||||
const File FileListComponent::getSelectedFile() const
|
||||
int FileListComponent::getNumSelectedFiles() const
|
||||
{
|
||||
return fileList.getFile (getSelectedRow());
|
||||
return getNumSelectedRows();
|
||||
}
|
||||
|
||||
const File FileListComponent::getSelectedFile (int index) const
|
||||
{
|
||||
return fileList.getFile (getSelectedRow (index));
|
||||
}
|
||||
|
||||
void FileListComponent::scrollToTop()
|
||||
|
|
@ -58107,12 +58203,7 @@ FileTreeComponent::~FileTreeComponent()
|
|||
delete root;
|
||||
}
|
||||
|
||||
const File FileTreeComponent::getSelectedFile() const
|
||||
{
|
||||
return getSelectedFile (0);
|
||||
}
|
||||
|
||||
const File FileTreeComponent::getSelectedFile (const int index) const throw()
|
||||
const File FileTreeComponent::getSelectedFile (const int index) const
|
||||
{
|
||||
const FileListTreeItem* const item = dynamic_cast <const FileListTreeItem*> (getSelectedItem (index));
|
||||
|
||||
|
|
@ -58245,21 +58336,14 @@ END_JUCE_NAMESPACE
|
|||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
WildcardFileFilter::WildcardFileFilter (const String& wildcardPatterns,
|
||||
WildcardFileFilter::WildcardFileFilter (const String& fileWildcardPatterns,
|
||||
const String& directoryWildcardPatterns,
|
||||
const String& description)
|
||||
: FileFilter (description.isEmpty() ? wildcardPatterns
|
||||
: (description + T(" (") + wildcardPatterns + T(")")))
|
||||
: FileFilter (description.isEmpty() ? fileWildcardPatterns
|
||||
: (description + T(" (") + fileWildcardPatterns + T(")")))
|
||||
{
|
||||
wildcards.addTokens (wildcardPatterns.toLowerCase(), T(";,"), T("\"'"));
|
||||
|
||||
wildcards.trim();
|
||||
wildcards.removeEmptyStrings();
|
||||
|
||||
// special case for *.*, because people use it to mean "any file", but it
|
||||
// would actually ignore files with no extension.
|
||||
for (int i = wildcards.size(); --i >= 0;)
|
||||
if (wildcards[i] == T("*.*"))
|
||||
wildcards.set (i, T("*"));
|
||||
parse (fileWildcardPatterns, fileWildcards);
|
||||
parse (directoryWildcardPatterns, directoryWildcards);
|
||||
}
|
||||
|
||||
WildcardFileFilter::~WildcardFileFilter()
|
||||
|
|
@ -58267,6 +58351,30 @@ WildcardFileFilter::~WildcardFileFilter()
|
|||
}
|
||||
|
||||
bool WildcardFileFilter::isFileSuitable (const File& file) const
|
||||
{
|
||||
return match (file, fileWildcards);
|
||||
}
|
||||
|
||||
bool WildcardFileFilter::isDirectorySuitable (const File& file) const
|
||||
{
|
||||
return match (file, directoryWildcards);
|
||||
}
|
||||
|
||||
void WildcardFileFilter::parse (const String& pattern, StringArray& result) throw()
|
||||
{
|
||||
result.addTokens (pattern.toLowerCase(), T(";,"), T("\"'"));
|
||||
|
||||
result.trim();
|
||||
result.removeEmptyStrings();
|
||||
|
||||
// special case for *.*, because people use it to mean "any file", but it
|
||||
// would actually ignore files with no extension.
|
||||
for (int i = result.size(); --i >= 0;)
|
||||
if (result[i] == T("*.*"))
|
||||
result.set (i, T("*"));
|
||||
}
|
||||
|
||||
bool WildcardFileFilter::match (const File& file, const StringArray& wildcards) throw()
|
||||
{
|
||||
const String filename (file.getFileName());
|
||||
|
||||
|
|
@ -58277,11 +58385,6 @@ bool WildcardFileFilter::isFileSuitable (const File& file) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool WildcardFileFilter::isDirectorySuitable (const File&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
/********* End of inlined file: juce_WildcardFileFilter.cpp *********/
|
||||
|
||||
|
|
@ -234860,6 +234963,14 @@ bool juce_launchFile (const String& fileName,
|
|||
return hInstance > (HINSTANCE) 32;
|
||||
}
|
||||
|
||||
void File::revealToUser() const throw()
|
||||
{
|
||||
if (isDirectory())
|
||||
startAsProcess();
|
||||
else if (getParentDirectory().exists())
|
||||
getParentDirectory().startAsProcess();
|
||||
}
|
||||
|
||||
struct NamedPipeInternal
|
||||
{
|
||||
HANDLE pipeH;
|
||||
|
|
@ -239483,6 +239594,7 @@ void FileChooser::showPlatformDialog (OwnedArray<File>& results,
|
|||
const File& currentFileOrDirectory,
|
||||
const String& filter,
|
||||
bool selectsDirectory,
|
||||
bool selectsFiles,
|
||||
bool isSaveDialogue,
|
||||
bool warnAboutOverwritingExistingFiles,
|
||||
bool selectMultipleFiles,
|
||||
|
|
@ -250774,10 +250886,11 @@ bool juce_launchFile (const String& fileName,
|
|||
cmdString << " " << parameters;
|
||||
|
||||
if (URL::isProbablyAWebsiteURL (fileName)
|
||||
|| cmdString.startsWithIgnoreCase (T("file:"))
|
||||
|| URL::isProbablyAnEmailAddress (fileName))
|
||||
{
|
||||
// create a command that tries to launch a bunch of likely browsers
|
||||
const char* const browserNames[] = { "/etc/alternatives/x-www-browser", "firefox", "mozilla", "konqueror", "opera" };
|
||||
const char* const browserNames[] = { "xdg-open", "/etc/alternatives/x-www-browser", "firefox", "mozilla", "konqueror", "opera" };
|
||||
|
||||
StringArray cmdLines;
|
||||
|
||||
|
|
@ -250787,9 +250900,6 @@ bool juce_launchFile (const String& fileName,
|
|||
cmdString = cmdLines.joinIntoString (T(" || "));
|
||||
}
|
||||
|
||||
if (cmdString.startsWithIgnoreCase (T("file:")))
|
||||
cmdString = cmdString.substring (5);
|
||||
|
||||
const char* const argv[4] = { "/bin/sh", "-c", (const char*) cmdString.toUTF8(), 0 };
|
||||
|
||||
const int cpid = fork();
|
||||
|
|
@ -250806,6 +250916,14 @@ bool juce_launchFile (const String& fileName,
|
|||
return cpid >= 0;
|
||||
}
|
||||
|
||||
void File::revealToUser() const throw()
|
||||
{
|
||||
if (isDirectory())
|
||||
startAsProcess();
|
||||
else if (getParentDirectory().exists())
|
||||
getParentDirectory().startAsProcess();
|
||||
}
|
||||
|
||||
#endif
|
||||
/********* End of inlined file: juce_linux_Files.cpp *********/
|
||||
|
||||
|
|
@ -258067,7 +258185,7 @@ MidiInput* MidiInput::createNewDevice (const String&, MidiInputCallback*) { re
|
|||
/********* Start of inlined file: juce_linux_AudioCDReader.cpp *********/
|
||||
// (This file gets included by juce_linux_NativeCode.cpp, rather than being
|
||||
// compiled on its own).
|
||||
#if JUCE_INCLUDED_FILE
|
||||
#if JUCE_INCLUDED_FILE && JUCE_USE_CDREADER
|
||||
|
||||
AudioCDReader::AudioCDReader()
|
||||
: AudioFormatReader (0, T("CD Audio"))
|
||||
|
|
@ -258151,6 +258269,7 @@ void FileChooser::showPlatformDialog (OwnedArray<File>& results,
|
|||
const File& file,
|
||||
const String& filters,
|
||||
bool isDirectory,
|
||||
bool selectsFiles,
|
||||
bool isSave,
|
||||
bool warnAboutOverwritingExistingFiles,
|
||||
bool selectMultipleFiles,
|
||||
|
|
@ -260343,6 +260462,16 @@ bool juce_launchFile (const String& fileName,
|
|||
#endif
|
||||
}
|
||||
|
||||
void File::revealToUser() const throw()
|
||||
{
|
||||
#if ! JUCE_IPHONE
|
||||
if (exists())
|
||||
[[NSWorkspace sharedWorkspace] selectFile: juceStringToNS (getFullPathName()) inFileViewerRootedAtPath: @""];
|
||||
else if (getParentDirectory().exists())
|
||||
getParentDirectory().revealToUser();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ! JUCE_IPHONE
|
||||
bool PlatformUtilities::makeFSRefFromPath (FSRef* destFSRef, const String& path)
|
||||
{
|
||||
|
|
@ -261505,18 +261634,27 @@ public:
|
|||
|
||||
bool clipToRectangleList (const RectangleList& clipRegion)
|
||||
{
|
||||
const int numRects = clipRegion.getNumRectangles();
|
||||
CGRect* const rects = new CGRect [numRects];
|
||||
for (int i = 0; i < numRects; ++i)
|
||||
if (clipRegion.isEmpty())
|
||||
{
|
||||
const Rectangle& r = clipRegion.getRectangle(i);
|
||||
rects[i] = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight());
|
||||
CGContextClipToRect (context, CGRectMake (0, 0, 0, 0));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int numRects = clipRegion.getNumRectangles();
|
||||
|
||||
CGContextClipToRects (context, rects, numRects);
|
||||
delete[] rects;
|
||||
CGRect* const rects = new CGRect [numRects];
|
||||
for (int i = 0; i < numRects; ++i)
|
||||
{
|
||||
const Rectangle& r = clipRegion.getRectangle(i);
|
||||
rects[i] = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight());
|
||||
}
|
||||
|
||||
return ! isClipEmpty();
|
||||
CGContextClipToRects (context, rects, numRects);
|
||||
delete[] rects;
|
||||
|
||||
return ! isClipEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
void excludeClipRectangle (const Rectangle& r)
|
||||
|
|
@ -263211,6 +263349,7 @@ void FileChooser::showPlatformDialog (OwnedArray<File>& results,
|
|||
const File& currentFileOrDirectory,
|
||||
const String& filter,
|
||||
bool selectsDirectory,
|
||||
bool selectsFiles,
|
||||
bool isSaveDialogue,
|
||||
bool warnAboutOverwritingExistingFiles,
|
||||
bool selectMultipleFiles,
|
||||
|
|
@ -263235,7 +263374,7 @@ void FileChooser::showPlatformDialog (OwnedArray<File>& results,
|
|||
{
|
||||
NSOpenPanel* openPanel = (NSOpenPanel*) panel;
|
||||
[openPanel setCanChooseDirectories: selectsDirectory];
|
||||
[openPanel setCanChooseFiles: ! selectsDirectory];
|
||||
[openPanel setCanChooseFiles: selectsFiles];
|
||||
[openPanel setAllowsMultipleSelection: selectMultipleFiles];
|
||||
}
|
||||
|
||||
|
|
@ -263283,6 +263422,7 @@ void FileChooser::showPlatformDialog (OwnedArray<File>& results,
|
|||
const File& currentFileOrDirectory,
|
||||
const String& filter,
|
||||
bool selectsDirectory,
|
||||
bool selectsFiles,
|
||||
bool isSaveDialogue,
|
||||
bool warnAboutOverwritingExistingFiles,
|
||||
bool selectMultipleFiles,
|
||||
|
|
@ -265962,18 +266102,27 @@ public:
|
|||
|
||||
bool clipToRectangleList (const RectangleList& clipRegion)
|
||||
{
|
||||
const int numRects = clipRegion.getNumRectangles();
|
||||
CGRect* const rects = new CGRect [numRects];
|
||||
for (int i = 0; i < numRects; ++i)
|
||||
if (clipRegion.isEmpty())
|
||||
{
|
||||
const Rectangle& r = clipRegion.getRectangle(i);
|
||||
rects[i] = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight());
|
||||
CGContextClipToRect (context, CGRectMake (0, 0, 0, 0));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int numRects = clipRegion.getNumRectangles();
|
||||
|
||||
CGContextClipToRects (context, rects, numRects);
|
||||
delete[] rects;
|
||||
CGRect* const rects = new CGRect [numRects];
|
||||
for (int i = 0; i < numRects; ++i)
|
||||
{
|
||||
const Rectangle& r = clipRegion.getRectangle(i);
|
||||
rects[i] = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight());
|
||||
}
|
||||
|
||||
return ! isClipEmpty();
|
||||
CGContextClipToRects (context, rects, numRects);
|
||||
delete[] rects;
|
||||
|
||||
return ! isClipEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
void excludeClipRectangle (const Rectangle& r)
|
||||
|
|
@ -269433,6 +269582,7 @@ void FileChooser::showPlatformDialog (OwnedArray<File>& results,
|
|||
const File& currentFileOrDirectory,
|
||||
const String& filter,
|
||||
bool selectsDirectory,
|
||||
bool selectsFiles,
|
||||
bool isSaveDialogue,
|
||||
bool warnAboutOverwritingExistingFiles,
|
||||
bool selectMultipleFiles,
|
||||
|
|
@ -269457,7 +269607,7 @@ void FileChooser::showPlatformDialog (OwnedArray<File>& results,
|
|||
{
|
||||
NSOpenPanel* openPanel = (NSOpenPanel*) panel;
|
||||
[openPanel setCanChooseDirectories: selectsDirectory];
|
||||
[openPanel setCanChooseFiles: ! selectsDirectory];
|
||||
[openPanel setCanChooseFiles: selectsFiles];
|
||||
[openPanel setAllowsMultipleSelection: selectMultipleFiles];
|
||||
}
|
||||
|
||||
|
|
@ -269505,6 +269655,7 @@ void FileChooser::showPlatformDialog (OwnedArray<File>& results,
|
|||
const File& currentFileOrDirectory,
|
||||
const String& filter,
|
||||
bool selectsDirectory,
|
||||
bool selectsFiles,
|
||||
bool isSaveDialogue,
|
||||
bool warnAboutOverwritingExistingFiles,
|
||||
bool selectMultipleFiles,
|
||||
|
|
|
|||
|
|
@ -6801,9 +6801,16 @@ public:
|
|||
default viewer application.
|
||||
|
||||
- if it's a folder, it will be opened in Explorer, Finder, or equivalent.
|
||||
|
||||
@see revealToUser
|
||||
*/
|
||||
bool startAsProcess (const String& parameters = String::empty) const throw();
|
||||
|
||||
/** Opens Finder, Explorer, or whatever the OS uses, to show the user this file's location.
|
||||
@see startAsProcess
|
||||
*/
|
||||
void revealToUser() const throw();
|
||||
|
||||
/** A set of types of location that can be passed to the getSpecialLocation() method.
|
||||
*/
|
||||
enum SpecialLocationType
|
||||
|
|
@ -11983,6 +11990,9 @@ public:
|
|||
bool isObject() const throw() { return type == objectType; }
|
||||
bool isMethod() const throw() { return type == methodType; }
|
||||
|
||||
bool operator== (const var& other) const throw();
|
||||
bool operator!= (const var& other) const throw();
|
||||
|
||||
class JUCE_API identifier
|
||||
{
|
||||
public:
|
||||
|
|
@ -50715,11 +50725,16 @@ public:
|
|||
/** Destructor. */
|
||||
virtual ~DirectoryContentsDisplayComponent();
|
||||
|
||||
/** Returns the file that the user has currently selected.
|
||||
|
||||
Returns File::nonexistent if none is selected.
|
||||
/** Returns the number of files the user has got selected.
|
||||
@see getSelectedFile
|
||||
*/
|
||||
virtual const File getSelectedFile() const = 0;
|
||||
virtual int getNumSelectedFiles() const = 0;
|
||||
|
||||
/** Returns one of the files that the user has currently selected.
|
||||
The index should be in the range 0 to (getNumSelectedFiles() - 1).
|
||||
@see getNumSelectedFiles
|
||||
*/
|
||||
virtual const File getSelectedFile (int index) const = 0;
|
||||
|
||||
/** Scrolls this view to the top. */
|
||||
virtual void scrollToTop() = 0;
|
||||
|
|
@ -50838,22 +50853,26 @@ class JUCE_API FileBrowserComponent : public Component,
|
|||
private FileBrowserListener,
|
||||
private TextEditorListener,
|
||||
private ButtonListener,
|
||||
private ComboBoxListener
|
||||
private ComboBoxListener,
|
||||
private FileFilter
|
||||
{
|
||||
public:
|
||||
|
||||
/** Various modes that the browser can be used in.
|
||||
/** Various options for the browser.
|
||||
|
||||
One of these is passed into the constructor.
|
||||
A combination of these is passed into the FileBrowserComponent constructor.
|
||||
*/
|
||||
enum FileChooserMode
|
||||
enum FileChooserFlags
|
||||
{
|
||||
loadFileMode, /**< the component should allow the user to choose an existing
|
||||
file with the intention of opening it. */
|
||||
saveFileMode, /**< the component should allow the user to specify the name of
|
||||
a file that will be used to save something. */
|
||||
chooseDirectoryMode /**< the component should allow the user to select an existing
|
||||
directory. */
|
||||
openMode = 1, /**< the component should allow the user to choose an existing
|
||||
file with the intention of opening it. */
|
||||
saveMode = 2, /**< the component should allow the user to specify the name of
|
||||
a file that will be used to save something. */
|
||||
canSelectFiles = 4, /**< */
|
||||
canSelectDirectories = 8, /**< */
|
||||
canSelectMultipleItems = 16, /**< */
|
||||
useTreeView = 32, /**< */
|
||||
filenameBoxIsReadOnly = 64 /**< */
|
||||
};
|
||||
|
||||
/** Creates a FileBrowserComponent.
|
||||
|
|
@ -50875,33 +50894,40 @@ public:
|
|||
@param filenameTextBoxIsReadOnly if true, the user won't be allowed to type their own
|
||||
text into the filename box.
|
||||
*/
|
||||
FileBrowserComponent (FileChooserMode browserMode,
|
||||
FileBrowserComponent (int flags,
|
||||
const File& initialFileOrDirectory,
|
||||
const FileFilter* fileFilter,
|
||||
FilePreviewComponent* previewComp,
|
||||
const bool useTreeView = false,
|
||||
const bool filenameTextBoxIsReadOnly = false);
|
||||
FilePreviewComponent* previewComp);
|
||||
|
||||
/** Destructor. */
|
||||
~FileBrowserComponent();
|
||||
|
||||
/** Returns the file that the user has currently chosen.
|
||||
/** Returns the number of files that the user has got selected.
|
||||
If multiple select isn't active, this will only be 0 or 1. To get the complete
|
||||
list of files they've chosen, pass an index to getCurrentFile().
|
||||
*/
|
||||
int getNumSelectedFiles() const throw();
|
||||
|
||||
/** Returns one of the files that the user has chosen.
|
||||
If the box has multi-select enabled, the index lets you specify which of the files
|
||||
to get - see getNumSelectedFiles() to find out how many files were chosen.
|
||||
@see getHighlightedFile
|
||||
*/
|
||||
const File getCurrentFile() const throw();
|
||||
const File getSelectedFile (int index) const throw();
|
||||
|
||||
/** Returns true if the current file is usable.
|
||||
/** Returns true if the currently selected file(s) are usable.
|
||||
|
||||
This can be used to decide whether the user can press "ok" for the
|
||||
current file. What it does depends on the mode, so for example in an "open"
|
||||
mode, the current file is only valid if one has been selected and if the file
|
||||
exists. In a "save" mode, a non-existent file would also be valid.
|
||||
mode, this only returns true if a file has been selected and if it exists.
|
||||
In a "save" mode, a non-existent file would also be valid.
|
||||
*/
|
||||
bool currentFileIsValid() const;
|
||||
|
||||
/** This returns the item in the view that is currently highlighted.
|
||||
/** This returns the last item in the view that the user has highlighted.
|
||||
This may be different from getCurrentFile(), which returns the value
|
||||
that is shown in the filename box.
|
||||
that is shown in the filename box, and if there are multiple selections,
|
||||
this will only return one of them.
|
||||
@see getCurrentFile
|
||||
*/
|
||||
const File getHighlightedFile() const throw();
|
||||
|
|
@ -50918,9 +50944,6 @@ public:
|
|||
/** Refreshes the directory that's currently being listed. */
|
||||
void refresh();
|
||||
|
||||
/** Returns the browser's current mode. */
|
||||
FileChooserMode getMode() const throw() { return mode; }
|
||||
|
||||
/** Returns a verb to describe what should happen when the file is accepted.
|
||||
|
||||
E.g. if browsing in "load file" mode, this will be "Open", if in "save file"
|
||||
|
|
@ -50928,6 +50951,10 @@ public:
|
|||
*/
|
||||
virtual const String getActionVerb() const;
|
||||
|
||||
/** Returns true if the saveMode flag was set when this component was created.
|
||||
*/
|
||||
bool isSaveMode() const throw();
|
||||
|
||||
/** Adds a listener to be told when the user selects and clicks on files.
|
||||
|
||||
@see removeListener
|
||||
|
|
@ -50962,6 +50989,10 @@ public:
|
|||
void fileClicked (const File& f, const MouseEvent& e);
|
||||
/** @internal */
|
||||
void fileDoubleClicked (const File& f);
|
||||
/** @internal */
|
||||
bool isFileSuitable (const File& file) const;
|
||||
/** @internal */
|
||||
bool isDirectorySuitable (const File&) const;
|
||||
|
||||
/** @internal */
|
||||
FilePreviewComponent* getPreviewComponent() const throw();
|
||||
|
|
@ -50974,10 +51005,11 @@ protected:
|
|||
private:
|
||||
|
||||
DirectoryContentsList* fileList;
|
||||
FileFilter* directoriesOnlyFilter;
|
||||
const FileFilter* fileFilter;
|
||||
|
||||
FileChooserMode mode;
|
||||
int flags;
|
||||
File currentRoot;
|
||||
OwnedArray <File> chosenFiles;
|
||||
SortedSet <void*> listeners;
|
||||
|
||||
DirectoryContentsDisplayComponent* fileListComponent;
|
||||
|
|
@ -50989,6 +51021,7 @@ private:
|
|||
TimeSliceThread thread;
|
||||
|
||||
void sendListenerChangeMessage();
|
||||
bool isFileOrDirSuitable (const File& f) const;
|
||||
|
||||
FileBrowserComponent (const FileBrowserComponent&);
|
||||
const FileBrowserComponent& operator= (const FileBrowserComponent&);
|
||||
|
|
@ -51112,6 +51145,13 @@ public:
|
|||
*/
|
||||
bool browseForDirectory();
|
||||
|
||||
/** Same as browseForFileToOpen, but allows the user to select multiple files and directories.
|
||||
|
||||
The files that are returned can be obtained by calling getResults(). See
|
||||
browseForFileToOpen() for more info about the behaviour of this method.
|
||||
*/
|
||||
bool browseForMultipleFilesOrDirectories (FilePreviewComponent* previewComponent = 0);
|
||||
|
||||
/** Returns the last file that was chosen by one of the browseFor methods.
|
||||
|
||||
After calling the appropriate browseFor... method, this method lets you
|
||||
|
|
@ -51145,7 +51185,8 @@ private:
|
|||
OwnedArray <File> results;
|
||||
bool useNativeDialogBox;
|
||||
|
||||
bool showDialog (const bool isDirectory,
|
||||
bool showDialog (const bool selectsDirectories,
|
||||
const bool selectsFiles,
|
||||
const bool isSave,
|
||||
const bool warnAboutOverwritingExistingFiles,
|
||||
const bool selectMultipleFiles,
|
||||
|
|
@ -51155,7 +51196,8 @@ private:
|
|||
const String& title,
|
||||
const File& file,
|
||||
const String& filters,
|
||||
bool isDirectory,
|
||||
bool selectsDirectories,
|
||||
bool selectsFiles,
|
||||
bool isSave,
|
||||
bool warnAboutOverwritingExistingFiles,
|
||||
bool selectMultipleFiles,
|
||||
|
|
@ -51320,11 +51362,16 @@ public:
|
|||
/** Destructor. */
|
||||
~FileListComponent();
|
||||
|
||||
/** Returns the file that the user has currently selected.
|
||||
|
||||
Returns File::nonexistent if none is selected.
|
||||
/** Returns the number of files the user has got selected.
|
||||
@see getSelectedFile
|
||||
*/
|
||||
const File getSelectedFile() const;
|
||||
int getNumSelectedFiles() const;
|
||||
|
||||
/** Returns one of the files that the user has currently selected.
|
||||
The index should be in the range 0 to (getNumSelectedFiles() - 1).
|
||||
@see getNumSelectedFiles
|
||||
*/
|
||||
const File getSelectedFile (int index = 0) const;
|
||||
|
||||
/** Scrolls to the top of the list. */
|
||||
void scrollToTop();
|
||||
|
|
@ -51389,21 +51436,16 @@ public:
|
|||
/** Destructor. */
|
||||
~FileTreeComponent();
|
||||
|
||||
/** Returns the number of selected files in the tree.
|
||||
/** Returns the number of files the user has got selected.
|
||||
@see getSelectedFile
|
||||
*/
|
||||
int getNumSelectedFiles() const throw() { return TreeView::getNumSelectedItems(); }
|
||||
int getNumSelectedFiles() const { return TreeView::getNumSelectedItems(); }
|
||||
|
||||
/** Returns one of the files that the user has currently selected.
|
||||
|
||||
Returns File::nonexistent if none is selected.
|
||||
The index should be in the range 0 to (getNumSelectedFiles() - 1).
|
||||
@see getNumSelectedFiles
|
||||
*/
|
||||
const File getSelectedFile (int index) const throw();
|
||||
|
||||
/** Returns the first of the files that the user has currently selected.
|
||||
|
||||
Returns File::nonexistent if none is selected.
|
||||
*/
|
||||
const File getSelectedFile() const;
|
||||
const File getSelectedFile (int index = 0) const;
|
||||
|
||||
/** Scrolls the list to the top. */
|
||||
void scrollToTop();
|
||||
|
|
@ -51752,7 +51794,8 @@ public:
|
|||
The description is a name to show the user in a list of possible patterns, so
|
||||
for the wav/aiff example, your description might be "audio files".
|
||||
*/
|
||||
WildcardFileFilter (const String& wildcardPatterns,
|
||||
WildcardFileFilter (const String& fileWildcardPatterns,
|
||||
const String& directoryWildcardPatterns,
|
||||
const String& description);
|
||||
|
||||
/** Destructor. */
|
||||
|
|
@ -51767,7 +51810,10 @@ public:
|
|||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
StringArray wildcards;
|
||||
StringArray fileWildcards, directoryWildcards;
|
||||
|
||||
static void parse (const String& pattern, StringArray& result) throw();
|
||||
static bool match (const File& file, const StringArray& wildcards) throw();
|
||||
};
|
||||
|
||||
#endif // __JUCE_WILDCARDFILEFILTER_JUCEHEADER__
|
||||
|
|
|
|||
|
|
@ -48,11 +48,16 @@ public:
|
|||
virtual ~DirectoryContentsDisplayComponent();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the file that the user has currently selected.
|
||||
|
||||
Returns File::nonexistent if none is selected.
|
||||
/** Returns the number of files the user has got selected.
|
||||
@see getSelectedFile
|
||||
*/
|
||||
virtual const File getSelectedFile() const = 0;
|
||||
virtual int getNumSelectedFiles() const = 0;
|
||||
|
||||
/** Returns one of the files that the user has currently selected.
|
||||
The index should be in the range 0 to (getNumSelectedFiles() - 1).
|
||||
@see getNumSelectedFiles
|
||||
*/
|
||||
virtual const File getSelectedFile (int index) const = 0;
|
||||
|
||||
/** Scrolls this view to the top. */
|
||||
virtual void scrollToTop() = 0;
|
||||
|
|
|
|||
|
|
@ -37,29 +37,24 @@ BEGIN_JUCE_NAMESPACE
|
|||
|
||||
|
||||
//==============================================================================
|
||||
class DirectoriesOnlyFilter : public FileFilter
|
||||
{
|
||||
public:
|
||||
DirectoriesOnlyFilter() : FileFilter (String::empty) {}
|
||||
|
||||
bool isFileSuitable (const File&) const { return false; }
|
||||
bool isDirectorySuitable (const File&) const { return true; }
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
FileBrowserComponent::FileBrowserComponent (FileChooserMode mode_,
|
||||
FileBrowserComponent::FileBrowserComponent (int flags_,
|
||||
const File& initialFileOrDirectory,
|
||||
const FileFilter* fileFilter,
|
||||
FilePreviewComponent* previewComp_,
|
||||
const bool useTreeView,
|
||||
const bool filenameTextBoxIsReadOnly)
|
||||
: directoriesOnlyFilter (0),
|
||||
mode (mode_),
|
||||
const FileFilter* fileFilter_,
|
||||
FilePreviewComponent* previewComp_)
|
||||
: FileFilter (String::empty),
|
||||
fileFilter (fileFilter_),
|
||||
flags (flags_),
|
||||
listeners (2),
|
||||
previewComp (previewComp_),
|
||||
thread ("Juce FileBrowser")
|
||||
{
|
||||
// You need to specify one or other of the open/save flags..
|
||||
jassert ((flags & (saveMode | openMode)) != 0);
|
||||
jassert ((flags & (saveMode | openMode)) != (saveMode | openMode));
|
||||
|
||||
// You need to specify at least one of these flags..
|
||||
jassert ((flags & (canSelectFiles | canSelectDirectories)) != 0);
|
||||
|
||||
String filename;
|
||||
|
||||
if (initialFileOrDirectory == File::nonexistent)
|
||||
|
|
@ -72,18 +67,20 @@ FileBrowserComponent::FileBrowserComponent (FileChooserMode mode_,
|
|||
}
|
||||
else
|
||||
{
|
||||
chosenFiles.add (new File (initialFileOrDirectory));
|
||||
currentRoot = initialFileOrDirectory.getParentDirectory();
|
||||
filename = initialFileOrDirectory.getFileName();
|
||||
}
|
||||
|
||||
if (mode_ == chooseDirectoryMode)
|
||||
fileFilter = directoriesOnlyFilter = new DirectoriesOnlyFilter();
|
||||
fileList = new DirectoryContentsList (this, thread);
|
||||
|
||||
fileList = new DirectoryContentsList (fileFilter, thread);
|
||||
|
||||
if (useTreeView)
|
||||
if ((flags & useTreeView) != 0)
|
||||
{
|
||||
FileTreeComponent* const tree = new FileTreeComponent (*fileList);
|
||||
|
||||
if ((flags & canSelectMultipleItems) != 0)
|
||||
tree->setMultiSelectEnabled (true);
|
||||
|
||||
addAndMakeVisible (tree);
|
||||
fileListComponent = tree;
|
||||
}
|
||||
|
|
@ -91,6 +88,10 @@ FileBrowserComponent::FileBrowserComponent (FileChooserMode mode_,
|
|||
{
|
||||
FileListComponent* const list = new FileListComponent (*fileList);
|
||||
list->setOutlineThickness (1);
|
||||
|
||||
if ((flags & canSelectMultipleItems) != 0)
|
||||
list->setMultipleSelectionEnabled (true);
|
||||
|
||||
addAndMakeVisible (list);
|
||||
fileListComponent = list;
|
||||
}
|
||||
|
|
@ -118,11 +119,11 @@ FileBrowserComponent::FileBrowserComponent (FileChooserMode mode_,
|
|||
filenameBox->setMultiLine (false);
|
||||
filenameBox->setSelectAllWhenFocused (true);
|
||||
filenameBox->setText (filename, false);
|
||||
filenameBox->addListener (this);
|
||||
filenameBox->setReadOnly (filenameTextBoxIsReadOnly);
|
||||
|
||||
Label* label = new Label ("f", (mode == chooseDirectoryMode) ? TRANS("folder:")
|
||||
: TRANS("file:"));
|
||||
filenameBox->addListener (this);
|
||||
filenameBox->setReadOnly ((flags & (filenameBoxIsReadOnly | canSelectMultipleItems)) != 0);
|
||||
|
||||
Label* label = new Label ("f", TRANS("file:"));
|
||||
addAndMakeVisible (label);
|
||||
label->attachToComponent (filenameBox, true);
|
||||
|
||||
|
|
@ -145,10 +146,7 @@ FileBrowserComponent::~FileBrowserComponent()
|
|||
removeChildComponent (previewComp);
|
||||
|
||||
deleteAllChildren();
|
||||
|
||||
deleteAndZero (fileList);
|
||||
delete directoriesOnlyFilter;
|
||||
|
||||
thread.stopThread (10000);
|
||||
}
|
||||
|
||||
|
|
@ -167,19 +165,33 @@ void FileBrowserComponent::removeListener (FileBrowserListener* const listener)
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
const File FileBrowserComponent::getCurrentFile() const throw()
|
||||
bool FileBrowserComponent::isSaveMode() const throw()
|
||||
{
|
||||
return currentRoot.getChildFile (filenameBox->getText());
|
||||
return (flags & saveMode) != 0;
|
||||
}
|
||||
|
||||
int FileBrowserComponent::getNumSelectedFiles() const throw()
|
||||
{
|
||||
if (chosenFiles.size() == 0 && currentFileIsValid())
|
||||
return 1;
|
||||
|
||||
return chosenFiles.size();
|
||||
}
|
||||
|
||||
const File FileBrowserComponent::getSelectedFile (int index) const throw()
|
||||
{
|
||||
if (! filenameBox->isReadOnly())
|
||||
return currentRoot.getChildFile (filenameBox->getText());
|
||||
else
|
||||
return chosenFiles[index] != 0 ? *chosenFiles[index] : File::nonexistent;
|
||||
}
|
||||
|
||||
bool FileBrowserComponent::currentFileIsValid() const
|
||||
{
|
||||
if (mode == saveFileMode)
|
||||
return ! getCurrentFile().isDirectory();
|
||||
else if (mode == loadFileMode)
|
||||
return getCurrentFile().existsAsFile();
|
||||
else if (mode == chooseDirectoryMode)
|
||||
return getCurrentFile().isDirectory();
|
||||
if (isSaveMode())
|
||||
return ! getSelectedFile (0).isDirectory();
|
||||
else
|
||||
return getSelectedFile (0).exists();
|
||||
|
||||
jassertfalse
|
||||
return false;
|
||||
|
|
@ -187,7 +199,28 @@ bool FileBrowserComponent::currentFileIsValid() const
|
|||
|
||||
const File FileBrowserComponent::getHighlightedFile() const throw()
|
||||
{
|
||||
return fileListComponent->getSelectedFile();
|
||||
return fileListComponent->getSelectedFile (0);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool FileBrowserComponent::isFileSuitable (const File& file) const
|
||||
{
|
||||
return (flags & canSelectFiles) != 0 ? (fileFilter == 0 || fileFilter->isFileSuitable (file))
|
||||
: false;
|
||||
}
|
||||
|
||||
bool FileBrowserComponent::isDirectorySuitable (const File&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileBrowserComponent::isFileOrDirSuitable (const File& f) const
|
||||
{
|
||||
if (f.isDirectory())
|
||||
return (flags & canSelectDirectories) != 0 && (fileFilter == 0 || fileFilter->isDirectorySuitable (f));
|
||||
|
||||
return (flags & canSelectFiles) != 0 && f.exists()
|
||||
&& (fileFilter == 0 || fileFilter->isFileSuitable (f));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -202,9 +235,6 @@ void FileBrowserComponent::setRoot (const File& newRootDirectory)
|
|||
{
|
||||
fileListComponent->scrollToTop();
|
||||
|
||||
if (mode == chooseDirectoryMode)
|
||||
filenameBox->setText (String::empty, false);
|
||||
|
||||
String path (newRootDirectory.getFullPathName());
|
||||
|
||||
if (path.isEmpty())
|
||||
|
|
@ -256,8 +286,7 @@ void FileBrowserComponent::refresh()
|
|||
|
||||
const String FileBrowserComponent::getActionVerb() const
|
||||
{
|
||||
return (mode == chooseDirectoryMode) ? TRANS("Choose")
|
||||
: ((mode == saveFileMode) ? TRANS("Save") : TRANS("Open"));
|
||||
return isSaveMode() ? TRANS("Save") : TRANS("Open");
|
||||
}
|
||||
|
||||
FilePreviewComponent* FileBrowserComponent::getPreviewComponent() const throw()
|
||||
|
|
@ -280,7 +309,7 @@ void FileBrowserComponent::sendListenerChangeMessage()
|
|||
ComponentDeletionWatcher deletionWatcher (this);
|
||||
|
||||
if (previewComp != 0)
|
||||
previewComp->selectedFileChanged (getCurrentFile());
|
||||
previewComp->selectedFileChanged (getSelectedFile (0));
|
||||
|
||||
jassert (! deletionWatcher.hasBeenDeleted());
|
||||
|
||||
|
|
@ -297,14 +326,29 @@ void FileBrowserComponent::sendListenerChangeMessage()
|
|||
|
||||
void FileBrowserComponent::selectionChanged()
|
||||
{
|
||||
const File selected (fileListComponent->getSelectedFile());
|
||||
StringArray newFilenames;
|
||||
bool resetChosenFiles = true;
|
||||
|
||||
if ((mode == chooseDirectoryMode && selected.isDirectory())
|
||||
|| selected.existsAsFile())
|
||||
for (int i = 0; i < fileListComponent->getNumSelectedFiles(); ++i)
|
||||
{
|
||||
filenameBox->setText (selected.getRelativePathFrom (getRoot()), false);
|
||||
const File f (fileListComponent->getSelectedFile (i));
|
||||
|
||||
if (isFileOrDirSuitable (f))
|
||||
{
|
||||
if (resetChosenFiles)
|
||||
{
|
||||
chosenFiles.clear();
|
||||
resetChosenFiles = false;
|
||||
}
|
||||
|
||||
chosenFiles.add (new File (f));
|
||||
newFilenames.add (f.getRelativePathFrom (getRoot()));
|
||||
}
|
||||
}
|
||||
|
||||
if (newFilenames.size() > 0)
|
||||
filenameBox->setText (newFilenames.joinIntoString (T(", ")), false);
|
||||
|
||||
sendListenerChangeMessage();
|
||||
}
|
||||
|
||||
|
|
@ -375,17 +419,20 @@ void FileBrowserComponent::textEditorReturnKeyPressed (TextEditor&)
|
|||
if (f.isDirectory())
|
||||
{
|
||||
setRoot (f);
|
||||
chosenFiles.clear();
|
||||
filenameBox->setText (String::empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
setRoot (f.getParentDirectory());
|
||||
chosenFiles.clear();
|
||||
chosenFiles.add (new File (f));
|
||||
filenameBox->setText (f.getFileName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fileDoubleClicked (getCurrentFile());
|
||||
fileDoubleClicked (getSelectedFile (0));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -395,7 +442,7 @@ void FileBrowserComponent::textEditorEscapeKeyPressed (TextEditor&)
|
|||
|
||||
void FileBrowserComponent::textEditorFocusLost (TextEditor&)
|
||||
{
|
||||
if (mode != saveFileMode)
|
||||
if (! isSaveMode())
|
||||
selectionChanged();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,22 +50,26 @@ class JUCE_API FileBrowserComponent : public Component,
|
|||
private FileBrowserListener,
|
||||
private TextEditorListener,
|
||||
private ButtonListener,
|
||||
private ComboBoxListener
|
||||
private ComboBoxListener,
|
||||
private FileFilter
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Various modes that the browser can be used in.
|
||||
/** Various options for the browser.
|
||||
|
||||
One of these is passed into the constructor.
|
||||
A combination of these is passed into the FileBrowserComponent constructor.
|
||||
*/
|
||||
enum FileChooserMode
|
||||
enum FileChooserFlags
|
||||
{
|
||||
loadFileMode, /**< the component should allow the user to choose an existing
|
||||
file with the intention of opening it. */
|
||||
saveFileMode, /**< the component should allow the user to specify the name of
|
||||
a file that will be used to save something. */
|
||||
chooseDirectoryMode /**< the component should allow the user to select an existing
|
||||
directory. */
|
||||
openMode = 1, /**< the component should allow the user to choose an existing
|
||||
file with the intention of opening it. */
|
||||
saveMode = 2, /**< the component should allow the user to specify the name of
|
||||
a file that will be used to save something. */
|
||||
canSelectFiles = 4, /**< */
|
||||
canSelectDirectories = 8, /**< */
|
||||
canSelectMultipleItems = 16, /**< */
|
||||
useTreeView = 32, /**< */
|
||||
filenameBoxIsReadOnly = 64 /**< */
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -88,34 +92,41 @@ public:
|
|||
@param filenameTextBoxIsReadOnly if true, the user won't be allowed to type their own
|
||||
text into the filename box.
|
||||
*/
|
||||
FileBrowserComponent (FileChooserMode browserMode,
|
||||
FileBrowserComponent (int flags,
|
||||
const File& initialFileOrDirectory,
|
||||
const FileFilter* fileFilter,
|
||||
FilePreviewComponent* previewComp,
|
||||
const bool useTreeView = false,
|
||||
const bool filenameTextBoxIsReadOnly = false);
|
||||
FilePreviewComponent* previewComp);
|
||||
|
||||
/** Destructor. */
|
||||
~FileBrowserComponent();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the file that the user has currently chosen.
|
||||
/** Returns the number of files that the user has got selected.
|
||||
If multiple select isn't active, this will only be 0 or 1. To get the complete
|
||||
list of files they've chosen, pass an index to getCurrentFile().
|
||||
*/
|
||||
int getNumSelectedFiles() const throw();
|
||||
|
||||
/** Returns one of the files that the user has chosen.
|
||||
If the box has multi-select enabled, the index lets you specify which of the files
|
||||
to get - see getNumSelectedFiles() to find out how many files were chosen.
|
||||
@see getHighlightedFile
|
||||
*/
|
||||
const File getCurrentFile() const throw();
|
||||
const File getSelectedFile (int index) const throw();
|
||||
|
||||
/** Returns true if the current file is usable.
|
||||
/** Returns true if the currently selected file(s) are usable.
|
||||
|
||||
This can be used to decide whether the user can press "ok" for the
|
||||
current file. What it does depends on the mode, so for example in an "open"
|
||||
mode, the current file is only valid if one has been selected and if the file
|
||||
exists. In a "save" mode, a non-existent file would also be valid.
|
||||
mode, this only returns true if a file has been selected and if it exists.
|
||||
In a "save" mode, a non-existent file would also be valid.
|
||||
*/
|
||||
bool currentFileIsValid() const;
|
||||
|
||||
/** This returns the item in the view that is currently highlighted.
|
||||
/** This returns the last item in the view that the user has highlighted.
|
||||
This may be different from getCurrentFile(), which returns the value
|
||||
that is shown in the filename box.
|
||||
that is shown in the filename box, and if there are multiple selections,
|
||||
this will only return one of them.
|
||||
@see getCurrentFile
|
||||
*/
|
||||
const File getHighlightedFile() const throw();
|
||||
|
|
@ -133,9 +144,6 @@ public:
|
|||
/** Refreshes the directory that's currently being listed. */
|
||||
void refresh();
|
||||
|
||||
/** Returns the browser's current mode. */
|
||||
FileChooserMode getMode() const throw() { return mode; }
|
||||
|
||||
/** Returns a verb to describe what should happen when the file is accepted.
|
||||
|
||||
E.g. if browsing in "load file" mode, this will be "Open", if in "save file"
|
||||
|
|
@ -143,6 +151,10 @@ public:
|
|||
*/
|
||||
virtual const String getActionVerb() const;
|
||||
|
||||
/** Returns true if the saveMode flag was set when this component was created.
|
||||
*/
|
||||
bool isSaveMode() const throw();
|
||||
|
||||
//==============================================================================
|
||||
/** Adds a listener to be told when the user selects and clicks on files.
|
||||
|
||||
|
|
@ -180,6 +192,10 @@ public:
|
|||
void fileClicked (const File& f, const MouseEvent& e);
|
||||
/** @internal */
|
||||
void fileDoubleClicked (const File& f);
|
||||
/** @internal */
|
||||
bool isFileSuitable (const File& file) const;
|
||||
/** @internal */
|
||||
bool isDirectorySuitable (const File&) const;
|
||||
|
||||
/** @internal */
|
||||
FilePreviewComponent* getPreviewComponent() const throw();
|
||||
|
|
@ -192,10 +208,11 @@ protected:
|
|||
private:
|
||||
//==============================================================================
|
||||
DirectoryContentsList* fileList;
|
||||
FileFilter* directoriesOnlyFilter;
|
||||
const FileFilter* fileFilter;
|
||||
|
||||
FileChooserMode mode;
|
||||
int flags;
|
||||
File currentRoot;
|
||||
OwnedArray <File> chosenFiles;
|
||||
SortedSet <void*> listeners;
|
||||
|
||||
DirectoryContentsDisplayComponent* fileListComponent;
|
||||
|
|
@ -207,6 +224,7 @@ private:
|
|||
TimeSliceThread thread;
|
||||
|
||||
void sendListenerChangeMessage();
|
||||
bool isFileOrDirSuitable (const File& f) const;
|
||||
|
||||
FileBrowserComponent (const FileBrowserComponent&);
|
||||
const FileBrowserComponent& operator= (const FileBrowserComponent&);
|
||||
|
|
|
|||
|
|
@ -120,9 +120,11 @@ bool FileChooser::showDialog (const bool selectsDirectories,
|
|||
&& previewComponent->getHeight() > 10));
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
if (useNativeDialogBox)
|
||||
#else
|
||||
if (useNativeDialogBox && ! (selectsFiles && selectsDirectories))
|
||||
#elif JUCE_MAC
|
||||
if (useNativeDialogBox && (previewComponent == 0))
|
||||
#else
|
||||
if (false)
|
||||
#endif
|
||||
{
|
||||
showPlatformDialog (results, title, startingFile, filters,
|
||||
|
|
@ -133,14 +135,23 @@ bool FileChooser::showDialog (const bool selectsDirectories,
|
|||
}
|
||||
else
|
||||
{
|
||||
jassert (! selectMultipleFiles); // not yet implemented for juce dialogs!
|
||||
WildcardFileFilter wildcard (selectsFiles ? filters : String::empty,
|
||||
selectsDirectories ? "*" : String::empty,
|
||||
String::empty);
|
||||
|
||||
WildcardFileFilter wildcard (filters, String::empty);
|
||||
int flags = isSave ? FileBrowserComponent::saveMode
|
||||
: FileBrowserComponent::openMode;
|
||||
|
||||
FileBrowserComponent browserComponent (selectsDirectories ? FileBrowserComponent::chooseDirectoryMode
|
||||
: (isSave ? FileBrowserComponent::saveFileMode
|
||||
: FileBrowserComponent::loadFileMode),
|
||||
startingFile, &wildcard, previewComponent);
|
||||
if (selectsFiles)
|
||||
flags |= FileBrowserComponent::canSelectFiles;
|
||||
|
||||
if (selectsDirectories)
|
||||
flags |= FileBrowserComponent::canSelectDirectories;
|
||||
|
||||
if (selectMultipleFiles)
|
||||
flags |= FileBrowserComponent::canSelectMultipleItems;
|
||||
|
||||
FileBrowserComponent browserComponent (flags, startingFile, &wildcard, previewComponent);
|
||||
|
||||
FileChooserDialogBox box (title, String::empty,
|
||||
browserComponent,
|
||||
|
|
@ -148,7 +159,10 @@ bool FileChooser::showDialog (const bool selectsDirectories,
|
|||
browserComponent.findColour (AlertWindow::backgroundColourId));
|
||||
|
||||
if (box.show())
|
||||
results.add (new File (browserComponent.getCurrentFile()));
|
||||
{
|
||||
for (int i = 0; i < browserComponent.getNumSelectedFiles(); ++i)
|
||||
results.add (new File (browserComponent.getSelectedFile (i)));
|
||||
}
|
||||
}
|
||||
|
||||
if (currentlyFocused != 0 && ! currentlyFocusedChecker->hasBeenDeleted())
|
||||
|
|
|
|||
|
|
@ -101,13 +101,13 @@ void FileChooserDialogBox::buttonClicked (Button* button)
|
|||
if (button == content->okButton)
|
||||
{
|
||||
if (warnAboutOverwritingExistingFiles
|
||||
&& content->chooserComponent->getMode() == FileBrowserComponent::saveFileMode
|
||||
&& content->chooserComponent->getCurrentFile().exists())
|
||||
&& content->chooserComponent->isSaveMode()
|
||||
&& content->chooserComponent->getSelectedFile(0).exists())
|
||||
{
|
||||
if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
|
||||
TRANS("File already exists"),
|
||||
TRANS("There's already a file called:\n\n")
|
||||
+ content->chooserComponent->getCurrentFile().getFullPathName()
|
||||
+ content->chooserComponent->getSelectedFile(0).getFullPathName()
|
||||
+ T("\n\nAre you sure you want to overwrite it?"),
|
||||
TRANS("overwrite"),
|
||||
TRANS("cancel")))
|
||||
|
|
|
|||
|
|
@ -50,9 +50,14 @@ FileListComponent::~FileListComponent()
|
|||
deleteAllChildren();
|
||||
}
|
||||
|
||||
const File FileListComponent::getSelectedFile() const
|
||||
int FileListComponent::getNumSelectedFiles() const
|
||||
{
|
||||
return fileList.getFile (getSelectedRow());
|
||||
return getNumSelectedRows();
|
||||
}
|
||||
|
||||
const File FileListComponent::getSelectedFile (int index) const
|
||||
{
|
||||
return fileList.getFile (getSelectedRow (index));
|
||||
}
|
||||
|
||||
void FileListComponent::scrollToTop()
|
||||
|
|
|
|||
|
|
@ -59,11 +59,16 @@ public:
|
|||
~FileListComponent();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the file that the user has currently selected.
|
||||
|
||||
Returns File::nonexistent if none is selected.
|
||||
/** Returns the number of files the user has got selected.
|
||||
@see getSelectedFile
|
||||
*/
|
||||
const File getSelectedFile() const;
|
||||
int getNumSelectedFiles() const;
|
||||
|
||||
/** Returns one of the files that the user has currently selected.
|
||||
The index should be in the range 0 to (getNumSelectedFiles() - 1).
|
||||
@see getNumSelectedFiles
|
||||
*/
|
||||
const File getSelectedFile (int index = 0) const;
|
||||
|
||||
/** Scrolls to the top of the list. */
|
||||
void scrollToTop();
|
||||
|
|
|
|||
|
|
@ -248,12 +248,7 @@ FileTreeComponent::~FileTreeComponent()
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
const File FileTreeComponent::getSelectedFile() const
|
||||
{
|
||||
return getSelectedFile (0);
|
||||
}
|
||||
|
||||
const File FileTreeComponent::getSelectedFile (const int index) const throw()
|
||||
const File FileTreeComponent::getSelectedFile (const int index) const
|
||||
{
|
||||
const FileListTreeItem* const item = dynamic_cast <const FileListTreeItem*> (getSelectedItem (index));
|
||||
|
||||
|
|
|
|||
|
|
@ -55,21 +55,16 @@ public:
|
|||
~FileTreeComponent();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of selected files in the tree.
|
||||
/** Returns the number of files the user has got selected.
|
||||
@see getSelectedFile
|
||||
*/
|
||||
int getNumSelectedFiles() const throw() { return TreeView::getNumSelectedItems(); }
|
||||
int getNumSelectedFiles() const { return TreeView::getNumSelectedItems(); }
|
||||
|
||||
/** Returns one of the files that the user has currently selected.
|
||||
|
||||
Returns File::nonexistent if none is selected.
|
||||
The index should be in the range 0 to (getNumSelectedFiles() - 1).
|
||||
@see getNumSelectedFiles
|
||||
*/
|
||||
const File getSelectedFile (int index) const throw();
|
||||
|
||||
/** Returns the first of the files that the user has currently selected.
|
||||
|
||||
Returns File::nonexistent if none is selected.
|
||||
*/
|
||||
const File getSelectedFile() const;
|
||||
const File getSelectedFile (int index = 0) const;
|
||||
|
||||
/** Scrolls the list to the top. */
|
||||
void scrollToTop();
|
||||
|
|
|
|||
|
|
@ -31,30 +31,46 @@ BEGIN_JUCE_NAMESPACE
|
|||
|
||||
|
||||
//==============================================================================
|
||||
WildcardFileFilter::WildcardFileFilter (const String& wildcardPatterns,
|
||||
WildcardFileFilter::WildcardFileFilter (const String& fileWildcardPatterns,
|
||||
const String& directoryWildcardPatterns,
|
||||
const String& description)
|
||||
: FileFilter (description.isEmpty() ? wildcardPatterns
|
||||
: (description + T(" (") + wildcardPatterns + T(")")))
|
||||
: FileFilter (description.isEmpty() ? fileWildcardPatterns
|
||||
: (description + T(" (") + fileWildcardPatterns + T(")")))
|
||||
{
|
||||
wildcards.addTokens (wildcardPatterns.toLowerCase(), T(";,"), T("\"'"));
|
||||
|
||||
wildcards.trim();
|
||||
wildcards.removeEmptyStrings();
|
||||
|
||||
// special case for *.*, because people use it to mean "any file", but it
|
||||
// would actually ignore files with no extension.
|
||||
for (int i = wildcards.size(); --i >= 0;)
|
||||
if (wildcards[i] == T("*.*"))
|
||||
wildcards.set (i, T("*"));
|
||||
parse (fileWildcardPatterns, fileWildcards);
|
||||
parse (directoryWildcardPatterns, directoryWildcards);
|
||||
}
|
||||
|
||||
WildcardFileFilter::~WildcardFileFilter()
|
||||
{
|
||||
}
|
||||
|
||||
bool WildcardFileFilter::isFileSuitable (const File& file) const
|
||||
{
|
||||
return match (file, fileWildcards);
|
||||
}
|
||||
|
||||
bool WildcardFileFilter::isDirectorySuitable (const File& file) const
|
||||
{
|
||||
return match (file, directoryWildcards);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool WildcardFileFilter::isFileSuitable (const File& file) const
|
||||
void WildcardFileFilter::parse (const String& pattern, StringArray& result) throw()
|
||||
{
|
||||
result.addTokens (pattern.toLowerCase(), T(";,"), T("\"'"));
|
||||
|
||||
result.trim();
|
||||
result.removeEmptyStrings();
|
||||
|
||||
// special case for *.*, because people use it to mean "any file", but it
|
||||
// would actually ignore files with no extension.
|
||||
for (int i = result.size(); --i >= 0;)
|
||||
if (result[i] == T("*.*"))
|
||||
result.set (i, T("*"));
|
||||
}
|
||||
|
||||
bool WildcardFileFilter::match (const File& file, const StringArray& wildcards) throw()
|
||||
{
|
||||
const String filename (file.getFileName());
|
||||
|
||||
|
|
@ -65,10 +81,5 @@ bool WildcardFileFilter::isFileSuitable (const File& file) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool WildcardFileFilter::isDirectorySuitable (const File&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -52,7 +52,8 @@ public:
|
|||
The description is a name to show the user in a list of possible patterns, so
|
||||
for the wav/aiff example, your description might be "audio files".
|
||||
*/
|
||||
WildcardFileFilter (const String& wildcardPatterns,
|
||||
WildcardFileFilter (const String& fileWildcardPatterns,
|
||||
const String& directoryWildcardPatterns,
|
||||
const String& description);
|
||||
|
||||
/** Destructor. */
|
||||
|
|
@ -65,12 +66,14 @@ public:
|
|||
/** This always returns true. */
|
||||
bool isDirectorySuitable (const File& file) const;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
StringArray wildcards;
|
||||
StringArray fileWildcards, directoryWildcards;
|
||||
|
||||
static void parse (const String& pattern, StringArray& result) throw();
|
||||
static bool match (const File& file, const StringArray& wildcards) throw();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue