Skip to content

Commit 0ee7252

Browse files
authored
Add drag-and-drop plugin validation to the main window (#170)
Drop a .vst3/.vst/.component/.dll/.so/.clap onto the pluginval window to validate it. Shows a highlighted overlay during the drag and routes through Validator::validate — the same flow used by "Test File...".
1 parent 4f99be4 commit 0ee7252

2 files changed

Lines changed: 101 additions & 0 deletions

File tree

Source/MainComponent.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
385409
void 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
//==============================================================================
423512
juce::StringArray MainComponent::getMenuBarNames()
424513
{

Source/MainComponent.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ class PluginTableComponent : public juce::Component,
381381
*/
382382
class MainComponent : public juce::Component,
383383
public juce::MenuBarModel,
384+
public juce::FileDragAndDropTarget,
384385
private juce::ChangeListener,
385386
private Validator::Listener
386387
{
@@ -391,6 +392,7 @@ class MainComponent : public juce::Component,
391392

392393
//==============================================================================
393394
void paint (juce::Graphics&) override;
395+
void paintOverChildren (juce::Graphics&) override;
394396
void resized() override;
395397

396398
//==============================================================================
@@ -399,6 +401,13 @@ class MainComponent : public juce::Component,
399401
juce::PopupMenu getMenuForIndex (int menuIndex, const juce::String& menuName) override;
400402
void menuItemSelected (int menuItemID, int topLevelMenuIndex) override;
401403

404+
//==============================================================================
405+
// FileDragAndDropTarget
406+
bool isInterestedInFileDrag (const juce::StringArray& files) override;
407+
void fileDragEnter (const juce::StringArray& files, int x, int y) override;
408+
void fileDragExit (const juce::StringArray& files) override;
409+
void filesDropped (const juce::StringArray& files, int x, int y) override;
410+
402411
private:
403412
//==============================================================================
404413
Validator& validator;
@@ -417,6 +426,9 @@ class MainComponent : public juce::Component,
417426
strictnessInfoButton { "Strictness" };
418427
StatusBar statusBar { validator };
419428
std::unique_ptr<StrictnessInfoDialog> strictnessDialog;
429+
bool dragHighlight = false;
430+
431+
static bool isPluginFile (const juce::String& path);
420432

421433
void savePluginList();
422434
juce::PopupMenu createFileMenu();

0 commit comments

Comments
 (0)