@@ -382,6 +382,30 @@ void MainComponent::paint (juce::Graphics& g)
382382 g.fillAll (getLookAndFeel ().findColour (juce::ResizableWindow::backgroundColourId));
383383}
384384
385+ void MainComponent::paintOverChildren (juce::Graphics& g)
386+ {
387+ if (! dragHighlight)
388+ return ;
389+
390+ constexpr float cornerRadius = 10 .0f ;
391+ constexpr float borderThickness = 3 .0f ;
392+ constexpr float inset = 6 .0f ;
393+ const auto accent = juce::Colour (0xff4a9eff );
394+
395+ auto r = getLocalBounds ().withTrimmedTop (menuBar.getBottom ())
396+ .toFloat ()
397+ .reduced (inset);
398+
399+ g.setColour (accent.withAlpha (0 .12f ));
400+ g.fillRoundedRectangle (r, cornerRadius);
401+
402+ g.setColour (accent);
403+ g.drawRoundedRectangle (r, cornerRadius, borderThickness);
404+
405+ g.setFont (juce::Font (juce::FontOptions (22 .0f , juce::Font::bold)));
406+ g.drawText (" Drop plug-in to validate" , r, juce::Justification::centred);
407+ }
408+
385409void MainComponent::resized ()
386410{
387411 auto r = getLocalBounds ();
@@ -419,6 +443,71 @@ void MainComponent::validationStarted (const juce::String&)
419443 tabbedComponent.setCurrentTabIndex (1 ); // Switch to Console tab
420444}
421445
446+ // ==============================================================================
447+ bool MainComponent::isPluginFile (const juce::String& path)
448+ {
449+ static const juce::StringArray extensions { " .vst3" , " .vst" , " .component" , " .dll" , " .so" , " .clap" };
450+ const auto lower = path.toLowerCase ();
451+
452+ for (const auto & ext : extensions)
453+ if (lower.endsWith (ext))
454+ return true ;
455+
456+ return false ;
457+ }
458+
459+ bool MainComponent::isInterestedInFileDrag (const juce::StringArray& files)
460+ {
461+ for (const auto & f : files)
462+ if (isPluginFile (f))
463+ return true ;
464+
465+ return false ;
466+ }
467+
468+ void MainComponent::fileDragEnter (const juce::StringArray& files, int , int )
469+ {
470+ const bool shouldHighlight = isInterestedInFileDrag (files);
471+
472+ if (dragHighlight != shouldHighlight)
473+ {
474+ dragHighlight = shouldHighlight;
475+ repaint ();
476+ }
477+ }
478+
479+ void MainComponent::fileDragExit (const juce::StringArray&)
480+ {
481+ if (dragHighlight)
482+ {
483+ dragHighlight = false ;
484+ repaint ();
485+ }
486+ }
487+
488+ void MainComponent::filesDropped (const juce::StringArray& files, int , int )
489+ {
490+ if (dragHighlight)
491+ {
492+ dragHighlight = false ;
493+ repaint ();
494+ }
495+
496+ juce::StringArray pluginFiles;
497+
498+ for (const auto & f : files)
499+ if (isPluginFile (f))
500+ pluginFiles.add (f);
501+
502+ if (pluginFiles.isEmpty ())
503+ return ;
504+
505+ getAppPreferences ().setValue (" lastPluginLocation" , pluginFiles[pluginFiles.size () - 1 ]);
506+
507+ validator.setValidateInProcess (getValidateInProcess ());
508+ validator.validate (pluginFiles, getTestOptions ());
509+ }
510+
422511// ==============================================================================
423512juce::StringArray MainComponent::getMenuBarNames ()
424513{
0 commit comments