osci-render/Source/components/EffectsListComponent.cpp

130 wiersze
5.4 KiB
C++

#include "EffectsListComponent.h"
#include "SvgButton.h"
#include "../PluginEditor.h"
#include "../LookAndFeel.h"
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, Effect& effect) : DraggableListBoxItem(lb, data, rn),
effect(effect), audioProcessor(data.audioProcessor), editor(data.editor) {
auto parameters = effect.parameters;
for (int i = 0; i < parameters.size(); i++) {
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(audioProcessor, effect, i);
selected.setToggleState(effect.enabled == nullptr || effect.enabled->getValue(), juce::dontSendNotification);
// using weak_ptr to avoid circular reference and memory leak
std::weak_ptr<EffectComponent> weakEffectComponent = effectComponent;
effectComponent->slider.setValue(parameters[i]->getValueUnnormalised(), juce::dontSendNotification);
effectComponent->slider.onValueChange = [this, i, weakEffectComponent] {
if (auto effectComponent = weakEffectComponent.lock()) {
this->effect.setValue(i, effectComponent->slider.getValue());
}
};
list.setEnabled(selected.getToggleState());
selected.onClick = [this, weakEffectComponent] {
if (auto effectComponent = weakEffectComponent.lock()) {
auto data = (AudioEffectListBoxItemData&)modelData;
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
data.setSelected(rowNum, selected.getToggleState());
list.setEnabled(selected.getToggleState());
}
repaint();
};
auto component = createComponent(parameters[i]);
if (component != nullptr) {
effectComponent->setComponent(component);
}
listModel.addComponent(effectComponent);
}
list.setColour(effectComponentBackgroundColourId, juce::Colours::transparentBlack.withAlpha(0.2f));
list.setModel(&listModel);
list.setRowHeight(ROW_HEIGHT);
list.updateContent();
addAndMakeVisible(list);
addAndMakeVisible(selected);
}
EffectsListComponent::~EffectsListComponent() {
list.setLookAndFeel(nullptr);
}
void EffectsListComponent::paint(juce::Graphics& g) {
auto bounds = getLocalBounds().removeFromLeft(LEFT_BAR_WIDTH);
g.setColour(findColour(effectComponentHandleColourId));
bounds.removeFromBottom(PADDING);
juce::Path path;
path.addRoundedRectangle(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), OscirenderLookAndFeel::RECT_RADIUS, OscirenderLookAndFeel::RECT_RADIUS, true, false, true, false);
g.fillPath(path);
g.setColour(juce::Colours::white);
// draw drag and drop handle using circles
double size = 4;
double leftPad = 4;
double spacing = 7;
double topPad = 6;
double y = bounds.getHeight() / 2 - 15;
g.fillEllipse(leftPad, y + topPad, size, size);
g.fillEllipse(leftPad, y + topPad + spacing, size, size);
g.fillEllipse(leftPad, y + topPad + 2 * spacing, size, size);
g.fillEllipse(leftPad + spacing, y + topPad, size, size);
g.fillEllipse(leftPad + spacing, y + topPad + spacing, size, size);
g.fillEllipse(leftPad + spacing, y + topPad + 2 * spacing, size, size);
DraggableListBoxItem::paint(g);
}
void EffectsListComponent::paintOverChildren(juce::Graphics& g) {
g.setColour(juce::Colours::black.withAlpha(0.3f));
auto bounds = list.getBounds();
bounds.removeFromBottom(PADDING);
juce::Path path;
path.addRoundedRectangle(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), OscirenderLookAndFeel::RECT_RADIUS, OscirenderLookAndFeel::RECT_RADIUS, false, true, false, true);
if (!selected.getToggleState()) {
g.fillPath(path);
}
}
void EffectsListComponent::resized() {
auto area = getLocalBounds();
auto leftBar = area.removeFromLeft(LEFT_BAR_WIDTH);
leftBar.removeFromLeft(20);
area.removeFromRight(PADDING);
selected.setBounds(leftBar.withSizeKeepingCentre(30, 20));
list.setBounds(area);
}
std::shared_ptr<juce::Component> EffectsListComponent::createComponent(EffectParameter* parameter) {
if (parameter->paramID == "customEffectStrength") {
std::shared_ptr<SvgButton> button = std::make_shared<SvgButton>(parameter->name, BinaryData::pencil_svg, juce::Colours::white, juce::Colours::red);
std::weak_ptr<SvgButton> weakButton = button;
button->setEdgeIndent(5);
button->setToggleState(editor.editingCustomFunction, juce::dontSendNotification);
button->setTooltip("Toggles whether the text editor is editing the currently open file, or the custom Lua effect.");
button->onClick = [this, weakButton] {
if (auto button = weakButton.lock()) {
editor.editCustomFunction(button->getToggleState());
}
};
return button;
}
return nullptr;
}
int EffectsListBoxModel::getRowHeight(int row) {
auto data = (AudioEffectListBoxItemData&)modelData;
return data.getEffect(row)->parameters.size() * EffectsListComponent::ROW_HEIGHT + EffectsListComponent::PADDING;
}
bool EffectsListBoxModel::hasVariableHeightRows() const {
return true;
}
juce::Component* EffectsListBoxModel::refreshComponentForRow(int rowNumber, bool isRowSelected, juce::Component *existingComponentToUpdate) {
std::unique_ptr<EffectsListComponent> item(dynamic_cast<EffectsListComponent*>(existingComponentToUpdate));
if (juce::isPositiveAndBelow(rowNumber, modelData.getNumItems())) {
auto data = (AudioEffectListBoxItemData&)modelData;
item = std::make_unique<EffectsListComponent>(listBox, (AudioEffectListBoxItemData&)modelData, rowNumber, *data.getEffect(rowNumber));
}
return item.release();
}