|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- /*
- ==============================================================================
-
- This file is part of the JUCE 6 technical preview.
- Copyright (c) 2020 - Raw Material Software Limited
-
- You may use this code under the terms of the GPL v3
- (see www.gnu.org/licenses).
-
- For this technical preview, this file is not subject to commercial licensing.
-
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
-
- ==============================================================================
- */
-
- namespace juce
- {
-
- FilenameComponent::FilenameComponent (const String& name,
- const File& currentFile,
- bool canEditFilename,
- bool isDirectory,
- bool isForSaving,
- const String& fileBrowserWildcard,
- const String& suffix,
- const String& textWhenNothingSelected)
- : Component (name),
- isDir (isDirectory),
- isSaving (isForSaving),
- wildcard (fileBrowserWildcard),
- enforcedSuffix (suffix)
- {
- addAndMakeVisible (filenameBox);
- filenameBox.setEditableText (canEditFilename);
- filenameBox.setTextWhenNothingSelected (textWhenNothingSelected);
- filenameBox.setTextWhenNoChoicesAvailable (TRANS ("(no recently selected files)"));
- filenameBox.onChange = [this] { setCurrentFile (getCurrentFile(), true); };
-
- setBrowseButtonText ("...");
-
- setCurrentFile (currentFile, true, dontSendNotification);
- }
-
- FilenameComponent::~FilenameComponent()
- {
- }
-
- //==============================================================================
- void FilenameComponent::paintOverChildren (Graphics& g)
- {
- if (isFileDragOver)
- {
- g.setColour (Colours::red.withAlpha (0.2f));
- g.drawRect (getLocalBounds(), 3);
- }
- }
-
- void FilenameComponent::resized()
- {
- getLookAndFeel().layoutFilenameComponent (*this, &filenameBox, browseButton.get());
- }
-
- KeyboardFocusTraverser* FilenameComponent::createFocusTraverser()
- {
- // This prevents the sub-components from grabbing focus if the
- // FilenameComponent has been set to refuse focus.
- return getWantsKeyboardFocus() ? Component::createFocusTraverser() : nullptr;
- }
-
- void FilenameComponent::setBrowseButtonText (const String& newBrowseButtonText)
- {
- browseButtonText = newBrowseButtonText;
- lookAndFeelChanged();
- }
-
- void FilenameComponent::lookAndFeelChanged()
- {
- browseButton.reset();
- browseButton.reset (getLookAndFeel().createFilenameComponentBrowseButton (browseButtonText));
- addAndMakeVisible (browseButton.get());
- browseButton->setConnectedEdges (Button::ConnectedOnLeft);
- browseButton->onClick = [this] { showChooser(); };
- resized();
- }
-
- void FilenameComponent::setTooltip (const String& newTooltip)
- {
- SettableTooltipClient::setTooltip (newTooltip);
- filenameBox.setTooltip (newTooltip);
- }
-
- void FilenameComponent::setDefaultBrowseTarget (const File& newDefaultDirectory)
- {
- defaultBrowseFile = newDefaultDirectory;
- }
-
- File FilenameComponent::getLocationToBrowse()
- {
- if (lastFilename.isEmpty() && defaultBrowseFile != File())
- return defaultBrowseFile;
-
- return getCurrentFile();
- }
-
- void FilenameComponent::showChooser()
- {
- #if JUCE_MODAL_LOOPS_PERMITTED
- FileChooser fc (isDir ? TRANS ("Choose a new directory")
- : TRANS ("Choose a new file"),
- getLocationToBrowse(),
- wildcard);
-
- if (isDir ? fc.browseForDirectory()
- : (isSaving ? fc.browseForFileToSave (false)
- : fc.browseForFileToOpen()))
- {
- setCurrentFile (fc.getResult(), true);
- }
- #else
- ignoreUnused (isSaving);
- jassertfalse; // needs rewriting to deal with non-modal environments
- #endif
- }
-
- bool FilenameComponent::isInterestedInFileDrag (const StringArray&)
- {
- return true;
- }
-
- void FilenameComponent::filesDropped (const StringArray& filenames, int, int)
- {
- isFileDragOver = false;
- repaint();
-
- const File f (filenames[0]);
-
- if (f.exists() && (f.isDirectory() == isDir))
- setCurrentFile (f, true);
- }
-
- void FilenameComponent::fileDragEnter (const StringArray&, int, int)
- {
- isFileDragOver = true;
- repaint();
- }
-
- void FilenameComponent::fileDragExit (const StringArray&)
- {
- isFileDragOver = false;
- repaint();
- }
-
- //==============================================================================
- String FilenameComponent::getCurrentFileText() const
- {
- return filenameBox.getText();
- }
-
- File FilenameComponent::getCurrentFile() const
- {
- auto f = File::getCurrentWorkingDirectory().getChildFile (getCurrentFileText());
-
- if (enforcedSuffix.isNotEmpty())
- f = f.withFileExtension (enforcedSuffix);
-
- return f;
- }
-
- void FilenameComponent::setCurrentFile (File newFile,
- const bool addToRecentlyUsedList,
- NotificationType notification)
- {
- if (enforcedSuffix.isNotEmpty())
- newFile = newFile.withFileExtension (enforcedSuffix);
-
- if (newFile.getFullPathName() != lastFilename)
- {
- lastFilename = newFile.getFullPathName();
-
- if (addToRecentlyUsedList)
- addRecentlyUsedFile (newFile);
-
- filenameBox.setText (lastFilename, dontSendNotification);
-
- if (notification != dontSendNotification)
- {
- triggerAsyncUpdate();
-
- if (notification == sendNotificationSync)
- handleUpdateNowIfNeeded();
- }
- }
- }
-
- void FilenameComponent::setFilenameIsEditable (const bool shouldBeEditable)
- {
- filenameBox.setEditableText (shouldBeEditable);
- }
-
- StringArray FilenameComponent::getRecentlyUsedFilenames() const
- {
- StringArray names;
-
- for (int i = 0; i < filenameBox.getNumItems(); ++i)
- names.add (filenameBox.getItemText (i));
-
- return names;
- }
-
- void FilenameComponent::setRecentlyUsedFilenames (const StringArray& filenames)
- {
- if (filenames != getRecentlyUsedFilenames())
- {
- filenameBox.clear();
-
- for (int i = 0; i < jmin (filenames.size(), maxRecentFiles); ++i)
- filenameBox.addItem (filenames[i], i + 1);
- }
- }
-
- void FilenameComponent::setMaxNumberOfRecentFiles (const int newMaximum)
- {
- maxRecentFiles = jmax (1, newMaximum);
-
- setRecentlyUsedFilenames (getRecentlyUsedFilenames());
- }
-
- void FilenameComponent::addRecentlyUsedFile (const File& file)
- {
- auto files = getRecentlyUsedFilenames();
-
- if (file.getFullPathName().isNotEmpty())
- {
- files.removeString (file.getFullPathName(), true);
- files.insert (0, file.getFullPathName());
-
- setRecentlyUsedFilenames (files);
- }
- }
-
- //==============================================================================
- void FilenameComponent::addListener (FilenameComponentListener* const listener)
- {
- listeners.add (listener);
- }
-
- void FilenameComponent::removeListener (FilenameComponentListener* const listener)
- {
- listeners.remove (listener);
- }
-
- void FilenameComponent::handleAsyncUpdate()
- {
- Component::BailOutChecker checker (this);
- listeners.callChecked (checker, [this] (FilenameComponentListener& l) { l.filenameComponentChanged (this); });
- }
-
- } // namespace juce
|