diff --git a/Source/MainComponent.cpp b/Source/MainComponent.cpp index f2e7537..44061be 100644 --- a/Source/MainComponent.cpp +++ b/Source/MainComponent.cpp @@ -382,6 +382,30 @@ void MainComponent::paint (juce::Graphics& g) g.fillAll (getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId)); } +void MainComponent::paintOverChildren (juce::Graphics& g) +{ + if (! dragHighlight) + return; + + constexpr float cornerRadius = 10.0f; + constexpr float borderThickness = 3.0f; + constexpr float inset = 6.0f; + const auto accent = juce::Colour (0xff4a9eff); + + auto r = getLocalBounds().withTrimmedTop (menuBar.getBottom()) + .toFloat() + .reduced (inset); + + g.setColour (accent.withAlpha (0.12f)); + g.fillRoundedRectangle (r, cornerRadius); + + g.setColour (accent); + g.drawRoundedRectangle (r, cornerRadius, borderThickness); + + g.setFont (juce::Font (juce::FontOptions (22.0f, juce::Font::bold))); + g.drawText ("Drop plug-in to validate", r, juce::Justification::centred); +} + void MainComponent::resized() { auto r = getLocalBounds(); @@ -419,6 +443,71 @@ void MainComponent::validationStarted (const juce::String&) tabbedComponent.setCurrentTabIndex (1); // Switch to Console tab } +//============================================================================== +bool MainComponent::isPluginFile (const juce::String& path) +{ + static const juce::StringArray extensions { ".vst3", ".vst", ".component", ".dll", ".so", ".clap" }; + const auto lower = path.toLowerCase(); + + for (const auto& ext : extensions) + if (lower.endsWith (ext)) + return true; + + return false; +} + +bool MainComponent::isInterestedInFileDrag (const juce::StringArray& files) +{ + for (const auto& f : files) + if (isPluginFile (f)) + return true; + + return false; +} + +void MainComponent::fileDragEnter (const juce::StringArray& files, int, int) +{ + const bool shouldHighlight = isInterestedInFileDrag (files); + + if (dragHighlight != shouldHighlight) + { + dragHighlight = shouldHighlight; + repaint(); + } +} + +void MainComponent::fileDragExit (const juce::StringArray&) +{ + if (dragHighlight) + { + dragHighlight = false; + repaint(); + } +} + +void MainComponent::filesDropped (const juce::StringArray& files, int, int) +{ + if (dragHighlight) + { + dragHighlight = false; + repaint(); + } + + juce::StringArray pluginFiles; + + for (const auto& f : files) + if (isPluginFile (f)) + pluginFiles.add (f); + + if (pluginFiles.isEmpty()) + return; + + getAppPreferences().setValue ("lastPluginLocation", pluginFiles[pluginFiles.size() - 1]); + + validator.setValidateInProcess (getValidateInProcess()); + validator.validate (pluginFiles, getTestOptions()); +} + //============================================================================== juce::StringArray MainComponent::getMenuBarNames() { diff --git a/Source/MainComponent.h b/Source/MainComponent.h index 7cfe8f8..22cc5e9 100644 --- a/Source/MainComponent.h +++ b/Source/MainComponent.h @@ -381,6 +381,7 @@ class PluginTableComponent : public juce::Component, */ class MainComponent : public juce::Component, public juce::MenuBarModel, + public juce::FileDragAndDropTarget, private juce::ChangeListener, private Validator::Listener { @@ -391,6 +392,7 @@ class MainComponent : public juce::Component, //============================================================================== void paint (juce::Graphics&) override; + void paintOverChildren (juce::Graphics&) override; void resized() override; //============================================================================== @@ -399,6 +401,13 @@ class MainComponent : public juce::Component, juce::PopupMenu getMenuForIndex (int menuIndex, const juce::String& menuName) override; void menuItemSelected (int menuItemID, int topLevelMenuIndex) override; + //============================================================================== + // FileDragAndDropTarget + bool isInterestedInFileDrag (const juce::StringArray& files) override; + void fileDragEnter (const juce::StringArray& files, int x, int y) override; + void fileDragExit (const juce::StringArray& files) override; + void filesDropped (const juce::StringArray& files, int x, int y) override; + private: //============================================================================== Validator& validator; @@ -417,6 +426,9 @@ class MainComponent : public juce::Component, strictnessInfoButton { "Strictness" }; StatusBar statusBar { validator }; std::unique_ptr strictnessDialog; + bool dragHighlight = false; + + static bool isPluginFile (const juce::String& path); void savePluginList(); juce::PopupMenu createFileMenu();