Skip to content

Commit 4c5adc2

Browse files
committed
Add validate / add-to-list drop zones to drag-and-drop validation
1 parent 9018c45 commit 4c5adc2

5 files changed

Lines changed: 91 additions & 35 deletions

File tree

CHANGELIST.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# pluginval Change List
22

33
### 1.0.5
4+
- Added drag-and-drop of plug-in files onto the main window, with two drop zones to either validate the plug-in or add it to the plugin list [#170]
45
- Added static linking to the Windows runtime so it should run on more Windows systems (particularly non-dev machines)
56
- Made `PluginInfoTest` run on the message thread as the functions it calls aren't thread-safe
67

Source/CommandLine.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,10 +534,10 @@ static void performCommandLine (CommandLineValidator& validator, const juce::Arg
534534
cli.addCommand ({ "--strictness-help",
535535
"--strictness-help [level]",
536536
"Lists all tests that run at the given strictness level.", juce::String(),
537-
[] (const auto& args)
537+
[] (const auto& commandArgs)
538538
{
539539
int level = 5;
540-
auto arg = getArgumentAfterOption (args, "--strictness-help");
540+
auto arg = getArgumentAfterOption (commandArgs, "--strictness-help");
541541
if (arg.text.isNotEmpty() && ! arg.isShortOption() && ! arg.isLongOption())
542542
level = arg.text.getIntValue();
543543
printStrictnessHelp (level);

Source/MainComponent.cpp

Lines changed: 76 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ MainComponent::MainComponent (Validator& v)
352352
{
353353
strictnessDialog = std::make_unique<StrictnessInfoDialog> (
354354
getStrictnessLevel(),
355-
[this, updateStrictnessButtonText] (int newLevel)
355+
[updateStrictnessButtonText] (int newLevel)
356356
{
357357
setStrictnessLevel (newLevel);
358358
updateStrictnessButtonText();
@@ -384,26 +384,45 @@ void MainComponent::paint (juce::Graphics& g)
384384

385385
void MainComponent::paintOverChildren (juce::Graphics& g)
386386
{
387-
if (! dragHighlight)
387+
if (dragAction == DropAction::none)
388388
return;
389389

390390
constexpr float cornerRadius = 10.0f;
391-
constexpr float borderThickness = 3.0f;
392391
constexpr float inset = 6.0f;
393-
const auto accent = juce::Colour (0xff4a9eff);
392+
constexpr float gap = 8.0f;
393+
const auto accent = juce::Colour (0xff4a9eff).withAlpha (0.9f);
394394

395-
auto r = getLocalBounds().withTrimmedTop (menuBar.getBottom())
396-
.toFloat()
397-
.reduced (inset);
395+
auto area = getDragOverlayBounds().toFloat().reduced (inset);
398396

399-
g.setColour (accent.withAlpha (0.12f));
400-
g.fillRoundedRectangle (r, cornerRadius);
397+
auto leftHalf = area.removeFromLeft ((area.getWidth() - gap) * 0.5f);
398+
area.removeFromLeft (gap);
399+
auto rightHalf = area;
401400

402-
g.setColour (accent);
403-
g.drawRoundedRectangle (r, cornerRadius, borderThickness);
401+
auto drawZone = [&] (juce::Rectangle<float> zone, const juce::String& title,
402+
const juce::String& subtitle, bool active)
403+
{
404+
auto bgCol = accent.withMultipliedSaturation (active ? 1.0f : 0.2f);
405+
g.setColour (bgCol);
406+
g.fillRoundedRectangle (zone, cornerRadius);
407+
408+
g.setColour (accent);
409+
g.drawRoundedRectangle (zone, cornerRadius, active ? 3.0f : 1.5f);
410+
411+
auto textArea = zone.reduced (12.0f);
412+
auto titleArea = textArea.removeFromTop (textArea.getHeight() * 0.5f);
413+
414+
g.setColour (bgCol.contrasting().withAlpha (active ? 1.0f : 0.6f));
415+
g.setFont (juce::Font (juce::FontOptions (24.0f, juce::Font::bold)));
416+
g.drawText (title, titleArea, juce::Justification::centredBottom);
404417

405-
g.setFont (juce::Font (juce::FontOptions (22.0f, juce::Font::bold)));
406-
g.drawText ("Drop plug-in to validate", r, juce::Justification::centred);
418+
g.setFont (juce::Font (juce::FontOptions (14.0f)));
419+
g.drawText (subtitle, textArea, juce::Justification::centredTop);
420+
};
421+
422+
drawZone (leftHalf, "Validate", "Run validation now",
423+
dragAction == DropAction::validate);
424+
drawZone (rightHalf, "Add to List", "Scan into the plug-in list",
425+
dragAction == DropAction::addToList);
407426
}
408427

409428
void MainComponent::resized()
@@ -468,31 +487,55 @@ bool MainComponent::isInterestedInFileDrag (const juce::StringArray& files)
468487
return false;
469488
}
470489

471-
void MainComponent::fileDragEnter (const juce::StringArray& files, int, int)
490+
juce::Rectangle<int> MainComponent::getDragOverlayBounds() const
472491
{
473-
const bool shouldHighlight = isInterestedInFileDrag (files);
492+
return getLocalBounds().withTrimmedTop (menuBar.getBottom());
493+
}
474494

475-
if (dragHighlight != shouldHighlight)
495+
MainComponent::DropAction MainComponent::dropActionForX (int x) const
496+
{
497+
return x < getDragOverlayBounds().getCentreX() ? DropAction::validate
498+
: DropAction::addToList;
499+
}
500+
501+
void MainComponent::updateDragAction (const juce::StringArray& files, int x)
502+
{
503+
const auto newAction = isInterestedInFileDrag (files) ? dropActionForX (x)
504+
: DropAction::none;
505+
506+
if (dragAction != newAction)
476507
{
477-
dragHighlight = shouldHighlight;
508+
dragAction = newAction;
478509
repaint();
479510
}
480511
}
481512

513+
void MainComponent::fileDragEnter (const juce::StringArray& files, int x, int)
514+
{
515+
updateDragAction (files, x);
516+
}
517+
518+
void MainComponent::fileDragMove (const juce::StringArray& files, int x, int)
519+
{
520+
updateDragAction (files, x);
521+
}
522+
482523
void MainComponent::fileDragExit (const juce::StringArray&)
483524
{
484-
if (dragHighlight)
525+
if (dragAction != DropAction::none)
485526
{
486-
dragHighlight = false;
527+
dragAction = DropAction::none;
487528
repaint();
488529
}
489530
}
490531

491-
void MainComponent::filesDropped (const juce::StringArray& files, int, int)
532+
void MainComponent::filesDropped (const juce::StringArray& files, int x, int)
492533
{
493-
if (dragHighlight)
534+
const auto action = dropActionForX (x);
535+
536+
if (dragAction != DropAction::none)
494537
{
495-
dragHighlight = false;
538+
dragAction = DropAction::none;
496539
repaint();
497540
}
498541

@@ -507,12 +550,17 @@ void MainComponent::filesDropped (const juce::StringArray& files, int, int)
507550

508551
getAppPreferences().setValue ("lastPluginLocation", pluginFiles[pluginFiles.size() - 1]);
509552

510-
juce::OwnedArray<juce::PluginDescription> typesFound;
511-
knownPluginList.scanAndAddDragAndDroppedFiles (formatManager, pluginFiles, typesFound);
512-
savePluginList();
513-
514-
validator.setValidateInProcess (getValidateInProcess());
515-
validator.validate (pluginFiles, getTestOptions());
553+
if (action == DropAction::addToList)
554+
{
555+
juce::OwnedArray<juce::PluginDescription> typesFound;
556+
knownPluginList.scanAndAddDragAndDroppedFiles (formatManager, pluginFiles, typesFound);
557+
savePluginList();
558+
}
559+
else
560+
{
561+
validator.setValidateInProcess (getValidateInProcess());
562+
validator.validate (pluginFiles, getTestOptions());
563+
}
516564
}
517565

518566
//==============================================================================

Source/MainComponent.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ class MainComponent : public juce::Component,
405405
// FileDragAndDropTarget
406406
bool isInterestedInFileDrag (const juce::StringArray& files) override;
407407
void fileDragEnter (const juce::StringArray& files, int x, int y) override;
408+
void fileDragMove (const juce::StringArray& files, int x, int y) override;
408409
void fileDragExit (const juce::StringArray& files) override;
409410
void filesDropped (const juce::StringArray& files, int x, int y) override;
410411

@@ -426,9 +427,16 @@ class MainComponent : public juce::Component,
426427
strictnessInfoButton { "Strictness" };
427428
StatusBar statusBar { validator };
428429
std::unique_ptr<StrictnessInfoDialog> strictnessDialog;
429-
bool dragHighlight = false;
430+
431+
// Which action a drop will perform, based on which half of the window the
432+
// drag is over. DropAction::none means no plug-in drag is in progress.
433+
enum class DropAction { none, validate, addToList };
434+
DropAction dragAction = DropAction::none;
430435

431436
static bool isPluginFile (const juce::String& path);
437+
juce::Rectangle<int> getDragOverlayBounds() const;
438+
DropAction dropActionForX (int x) const;
439+
void updateDragAction (const juce::StringArray& files, int x);
432440

433441
void savePluginList();
434442
juce::PopupMenu createFileMenu();

Source/PluginvalLookAndFeel.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ class PluginvalLookAndFeel : public juce::LookAndFeel_V4
4444
const auto textColour = juce::Colour (0xffe0e0e0);
4545
const auto textDimmed = juce::Colour (0xff909090);
4646
const auto accentColour = juce::Colour (0xffffffff);
47-
const auto highlightColour = getAccentColour().withAlpha (0.3f);
4847

4948
// Window colours
5049
setColour (juce::ResizableWindow::backgroundColourId, backgroundDark);
@@ -194,7 +193,7 @@ class PluginvalLookAndFeel : public juce::LookAndFeel_V4
194193
g.drawEllipse (juce::Rectangle<float> (thumbWidth, thumbWidth).withCentre (thumbPoint), 1.0f);
195194
}
196195

197-
void drawTabButton (juce::TabBarButton& button, juce::Graphics& g, bool isMouseOver, bool isMouseDown) override
196+
void drawTabButton (juce::TabBarButton& button, juce::Graphics& g, bool isMouseOver, bool /*isMouseDown*/) override
198197
{
199198
auto area = button.getActiveArea().toFloat();
200199
auto backgroundColour = findColour (juce::ResizableWindow::backgroundColourId);
@@ -219,7 +218,7 @@ class PluginvalLookAndFeel : public juce::LookAndFeel_V4
219218
g.drawText (button.getButtonText(), area.reduced (12.0f, 0.0f), juce::Justification::centred);
220219
}
221220

222-
int getTabButtonBestWidth (juce::TabBarButton& button, int tabDepth) override
221+
int getTabButtonBestWidth (juce::TabBarButton& button, int /*tabDepth*/) override
223222
{
224223
auto width = juce::GlyphArrangement::getStringWidthInt (juce::Font (juce::FontOptions (14.0f)), button.getButtonText()) + 40; // Extra padding
225224
return juce::jmax (width, 80);
@@ -236,7 +235,7 @@ class PluginvalLookAndFeel : public juce::LookAndFeel_V4
236235
}
237236

238237
void drawTableHeaderColumn (juce::Graphics& g, juce::TableHeaderComponent& header,
239-
const juce::String& columnName, int columnId,
238+
const juce::String& columnName, int /*columnId*/,
240239
int width, int height, bool isMouseOver, bool isMouseDown,
241240
int columnFlags) override
242241
{

0 commit comments

Comments
 (0)