Skip to content

Commit

Permalink
Merge pull request #28 from segwin/dropdown
Browse files Browse the repository at this point in the history
Dropdown
  • Loading branch information
almalh authored Apr 1, 2018
2 parents fa38368 + 0da86d1 commit 986c5f3
Show file tree
Hide file tree
Showing 11 changed files with 141 additions and 39 deletions.
92 changes: 87 additions & 5 deletions Source/PluginEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ namespace reverb
AudioProcessorEditor::AudioProcessorEditor(AudioProcessor& p)
: juce::AudioProcessorEditor(&p), processor(p), parameters(p.parameters),
headerBlock(p), graphBlock(p), reverbBlock(p),
lowShelfFilterBlock(p,0), peakLowFilterBlock(p,1),
peakHighFilterBlock(p,2), highShelfFilterBlock(p,3),
lowShelfFilterBlock(p, 0, "low-shelf filter"), peakLowFilterBlock(p, 1, "low-peak filter"),
peakHighFilterBlock(p, 2, "high-peak filter"), highShelfFilterBlock(p, 3, "high-shelf filter"),
filterBlocks({ &lowShelfFilterBlock, &peakLowFilterBlock, &peakHighFilterBlock, &highShelfFilterBlock })
{
// Make sure that before the constructor has finished, you've set the
// editor's size to whatever you need it to be.
{
// Make sure that before the constructor has finished, you've set the
// editor's size to whatever you need it to be.
setResizable(true, true);
setResizeLimits(800, 640, 1920, 1080);

Expand All @@ -62,6 +62,7 @@ namespace reverb

// Set listeners for IR graph
headerBlock.irChoice.addListener(&graphBlock);
headerBlock.irChoice.addListener(this);

reverbBlock.irLength.addListener(&graphBlock);
reverbBlock.preDelay.addListener(&graphBlock);
Expand Down Expand Up @@ -158,4 +159,85 @@ namespace reverb
}
}

/**
* @brief Callback function to open the popup menu asynchronously.
*
* @details This function will open a popup menu when the user clicks
* on the IR selection's button. The first item in the menu
* will let the user choose a custom IR from a file browser,
* while the other items will display the IRs from the IR bank.
* @param [in] clickedButton Pointer to the button clicked by the user.
*/
void AudioProcessorEditor::buttonClicked(juce::Button* clickedButton)
{
if (clickedButton != nullptr && clickedButton == &headerBlock.irChoice) {
juce::PopupMenu m;
m.addItem(1, "Load custom IR...");
m.addSeparator();

for (int i = 0; i < headerBlock.previousSelectedIRs.size(); i++)
{
m.addItem(i + 2, headerBlock.previousSelectedIRs[i]);
}

m.addSeparator();

for (auto irFile : IRBank::getInstance().buffers)
{
m.addItem(m.getNumItems() + 1, irFile.first);
}

m.showMenuAsync(juce::PopupMenu::Options(),
juce::ModalCallbackFunction::forComponent(menuCallback, &headerBlock));
}
}

/**
* @brief Callback function to open the popup menu asynchronously.
*
* @details This function will open a file browser if the user clicked on the first
* item in the dropdown menu. Any other item will load the appropriate IR
* from the IR bank.
* @param [in] result The index of the item selected by the user.
* [in] headerBlock Pointer to the header block.
*/
void AudioProcessorEditor::menuCallback(int result, UIHeaderBlock* headerBlock)
{
if (headerBlock != nullptr && result != 0)
{
auto irName = headerBlock->parameters.state.getChildWithName(AudioProcessor::PID_IR_FILE_CHOICE);
juce::String selectedIR;
if (result == 1)
{
juce::AudioFormatManager formatManager;
formatManager.registerBasicFormats();
// Accepts the following file types: .wav, .bwf, .aiff, .flac, .ogg, .mp3, .wmv, .asf, .wm, .wma
juce::FileChooser fileChooser("Select an impulse response",
juce::File::getCurrentWorkingDirectory(),
formatManager.getWildcardForAllFormats(),
false);
if (fileChooser.browseForFileToOpen())
{
selectedIR = fileChooser.getResult().getFullPathName();
irName.setProperty("value", selectedIR, nullptr);
headerBlock->irChoice.setButtonText(selectedIR);
headerBlock->previousSelectedIRs.add(selectedIR);
}
}
else if (result <= (headerBlock->previousSelectedIRs.size() + 1))
{
selectedIR = headerBlock->previousSelectedIRs[result - 2];
irName.setProperty("value", selectedIR, nullptr);
headerBlock->irChoice.setButtonText(selectedIR);
}
else
{
selectedIR = std::next(IRBank::getInstance().buffers.begin(),
result - headerBlock->previousSelectedIRs.size() - 2)->first;
irName.setProperty("value", selectedIR, nullptr);
headerBlock->irChoice.setButtonText(selectedIR);
}
}
}

}
33 changes: 16 additions & 17 deletions Source/PluginEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,32 @@
namespace reverb
{

//==============================================================================
/**
//==============================================================================
/**
* Implements the plugins UI. This includes window configuration, placement of UI elements
* and handlers for various events such as slider interaction.
*/
class AudioProcessorEditor : public juce::AudioProcessorEditor
{
public:
AudioProcessorEditor(AudioProcessor&);
~AudioProcessorEditor();
*/
class AudioProcessorEditor : public juce::AudioProcessorEditor,
public juce::Button::Listener
{
public:
AudioProcessorEditor(AudioProcessor&);
~AudioProcessorEditor();

//==============================================================================
void paint(juce::Graphics&) override;
void resized() override;
//==============================================================================
void paint(juce::Graphics&) override;
void resized() override;

//==============================================================================
//void buttonClicked(juce::Button * button) override;
/*void loadIR(int num);
void handleMenuResult(int result);
void menuCallback(int result);*/
void buttonClicked(juce::Button* button) override;
static void menuCallback(int result, UIHeaderBlock* headerBlock);

//==============================================================================
static constexpr double PADDING_REL = 0.02; // 2% padding

protected:
protected:
//==============================================================================
AudioProcessor& processor;
AudioProcessor& processor;
juce::AudioProcessorValueTreeState& parameters;

//==============================================================================
Expand Down
6 changes: 4 additions & 2 deletions Source/UIBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
namespace reverb
{

UIBlock::UIBlock(int numComponents, int numComponentsPerRow)
: numComponents(numComponents), numComponentsPerRow(numComponentsPerRow)
UIBlock::UIBlock(int numComponents, int numComponentsPerRow,
const juce::String& componentName, const juce::String &labelText)
: numComponents(numComponents), numComponentsPerRow(numComponentsPerRow),
juce::GroupComponent(componentName, labelText)
{
frame.setClickingTogglesState(false);
frame.setInterceptsMouseClicks(false, true);
Expand Down
5 changes: 3 additions & 2 deletions Source/UIBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
namespace reverb
{

class UIBlock : public juce::Component
class UIBlock : public juce::GroupComponent
{
public:
//==============================================================================
UIBlock(int numComponents, int numComponentsPerRow);
UIBlock(int numComponents, int numComponentsPerRow,
const juce::String& componentName = juce::String(), const juce::String &labelText = juce::String());

//==============================================================================
using Ptr = std::unique_ptr<UIBlock>;
Expand Down
13 changes: 9 additions & 4 deletions Source/UIFilterBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ namespace reverb
* for a filter as well as does most of its configuration. It also adds its
* parameters to the AudioProcessorValueTreeState.
*/
UIFilterBlock::UIFilterBlock(AudioProcessor& processor, int index)
: UIBlock(3, 2)
UIFilterBlock::UIFilterBlock(AudioProcessor& processor, int index, const juce::String& displayedName)
: UIBlock(3, 2, "Filter", displayedName)
{
// Sliders
freq.setSliderStyle(juce::Slider::RotaryVerticalDrag);
Expand Down Expand Up @@ -97,6 +97,10 @@ namespace reverb

g.setColour(juce::Colours::white);
g.setFont(15.0f);

juce::Rectangle<int> bounds(getLocalBounds());
getLookAndFeel().drawGroupComponentOutline(g, bounds.getWidth(), bounds.getHeight(), getText(),
juce::Justification(juce::Justification::centredTop), *this);
}

//==============================================================================
Expand All @@ -110,8 +114,9 @@ namespace reverb
{
juce::Rectangle<int> bounds(getLocalBounds());

// Draw frame
// TODO: Make this look nice
int height = bounds.getHeight();
int padding = (int)(height * 0.06);
bounds.reduce(padding, padding);

// Distribute elements in columns
auto cells = getComponentCells(bounds);
Expand Down
3 changes: 2 additions & 1 deletion Source/UIFilterBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ namespace reverb {
{
public:
//==============================================================================
UIFilterBlock(AudioProcessor& processor, int index);
UIFilterBlock(AudioProcessor& processor, int index,
const juce::String& displayedName = juce::String());

//==============================================================================
using Ptr = std::unique_ptr<UIFilterBlock>;
Expand Down
6 changes: 5 additions & 1 deletion Source/UIGraphBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace reverb
* is updated periodically and on notify in a separate thread.
*/
UIGraphBlock::UIGraphBlock(AudioProcessor& processor)
: processor(processor)
: processor(processor), juce::GroupComponent("IR Graph", "waveform - impulse response")
{
graphThread.reset(new std::thread(&UIGraphBlock::updateGraph, this, 100));
}
Expand Down Expand Up @@ -53,6 +53,10 @@ namespace reverb
{
g.strokePath(irPlot, juce::PathStrokeType(1.0f));
}

juce::Rectangle<int> bounds(getLocalBounds());
getLookAndFeel().drawGroupComponentOutline(g, bounds.getWidth(), bounds.getHeight(), getText(),
juce::Justification(juce::Justification::centredTop), *this);
}

//==============================================================================
Expand Down
2 changes: 1 addition & 1 deletion Source/UIGraphBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace reverb
{

//==============================================================================
class UIGraphBlock : public juce::Component,
class UIGraphBlock : public juce::GroupComponent,
public juce::Button::Listener,
public juce::ComboBox::Listener,
public juce::Slider::Listener
Expand Down
6 changes: 3 additions & 3 deletions Source/UIHeaderBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ namespace reverb

//==============================================================================
UIHeaderBlock::UIHeaderBlock(AudioProcessor& p)
: UIBlock(3, 3)
: UIBlock(3, 3, "Header", "reverb settings"),
parameters(p.parameters),
previousSelectedIRs(juce::StringArray())
{
// State button
isOn.setButtonText("STATE");
Expand Down Expand Up @@ -44,8 +46,6 @@ namespace reverb
irChoiceLabel.setJustificationType(juce::Justification::topLeft);
irChoiceLabel.attachToComponent(&irChoice, false);

// TODO: Ensure IR file box tracks the IR choice parameter

// Sample rate box
auto sampleRateTemp = std::to_string(p.getSampleRate() / 1000);

Expand Down
3 changes: 3 additions & 0 deletions Source/UIHeaderBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ namespace reverb
juce::TextButton irChoice;
juce::TextButton sampleRate;

juce::AudioProcessorValueTreeState& parameters;
juce::StringArray previousSelectedIRs;

protected:
//==============================================================================
using ButtonAttachment = juce::AudioProcessorValueTreeState::ButtonAttachment;
Expand Down
11 changes: 8 additions & 3 deletions Source/UIReverbBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace reverb
* parameters to the AudioProcessorValueTreeState.
*/
UIReverbBlock::UIReverbBlock(AudioProcessor& processor)
: UIBlock(5, 2)
: UIBlock(5, 2, "Reverb", "reverb parameters")
{
// Sliders
irLength.setSliderStyle(juce::Slider::RotaryVerticalDrag);
Expand Down Expand Up @@ -123,6 +123,10 @@ namespace reverb

g.setColour(juce::Colours::white);
g.setFont(15.0f);

juce::Rectangle<int> bounds(getLocalBounds());
getLookAndFeel().drawGroupComponentOutline(g, bounds.getWidth(), bounds.getHeight(), getText(),
juce::Justification(juce::Justification::centredTop), *this);
}

//==============================================================================
Expand All @@ -136,8 +140,9 @@ namespace reverb
{
juce::Rectangle<int> bounds(getLocalBounds());

// Draw frame
// TODO: Make this look nice
int height = bounds.getHeight();
int padding = (int)(height * 0.06);
bounds.reduce(padding, padding);

// Distribute child elements in columns
auto cells = getComponentCells(bounds);
Expand Down

0 comments on commit 986c5f3

Please sign in to comment.