Start improving design of effect component lists

pull/170/head
James Ball 2023-12-03 22:37:38 +00:00
rodzic 3ab190398b
commit 50cc383e25
5 zmienionych plików z 173 dodań i 55 usunięć

Wyświetl plik

@ -45,11 +45,13 @@ OscirenderLookAndFeel::OscirenderLookAndFeel() {
void OscirenderLookAndFeel::drawComboBox(juce::Graphics& g, int width, int height, bool, int, int, int, int, juce::ComboBox& box) {
juce::Rectangle<int> boxBounds{0, 0, width, height};
float alpha = box.isEnabled() ? 1.0f : 0.5f;
g.setColour(box.findColour(juce::ComboBox::backgroundColourId));
g.setColour(box.findColour(juce::ComboBox::backgroundColourId).withAlpha(alpha));
g.fillRect(boxBounds.toFloat());
g.setColour(box.findColour(juce::ComboBox::outlineColourId));
g.setColour(box.findColour(juce::ComboBox::outlineColourId).withAlpha(alpha));
g.drawRect(boxBounds.toFloat().reduced(0.5f, 0.5f), 1.0f);
juce::Rectangle<int> arrowZone{width - 15, 0, 10, height};
@ -59,7 +61,7 @@ void OscirenderLookAndFeel::drawComboBox(juce::Graphics& g, int width, int heigh
path.lineTo((float)arrowZone.getRight(), (float)arrowZone.getCentreY() - 3.0f);
path.closeSubPath();
g.setColour(box.findColour(juce::ComboBox::arrowColourId).withAlpha((box.isEnabled() ? 0.9f : 0.2f)));
g.setColour(box.findColour(juce::ComboBox::arrowColourId).withAlpha(alpha));
g.fillPath(path);
}
@ -138,8 +140,102 @@ void OscirenderLookAndFeel::drawGroupComponentOutline(juce::Graphics& g, int wid
}
void OscirenderLookAndFeel::drawLinearSlider(juce::Graphics& g, int x, int y, int width, int height, float sliderPos, float minSliderPos, float maxSliderPos, const juce::Slider::SliderStyle style, juce::Slider& slider) {
juce::LookAndFeel_V4::drawLinearSlider(g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
float alpha = slider.isEnabled() ? 1.0f : 0.5f;
if (slider.isBar())
{
g.setColour (slider.findColour (juce::Slider::trackColourId).withAlpha(alpha));
g.fillRect (slider.isHorizontal() ? juce::Rectangle<float> (static_cast<float> (x), (float) y + 0.5f, sliderPos - (float) x, (float) height - 1.0f)
: juce::Rectangle<float> ((float) x + 0.5f, sliderPos, (float) width - 1.0f, (float) y + ((float) height - sliderPos)));
drawLinearSliderOutline (g, x, y, width, height, style, slider);
}
else
{
auto isTwoVal = (style == juce::Slider::SliderStyle::TwoValueVertical || style == juce::Slider::SliderStyle::TwoValueHorizontal);
auto isThreeVal = (style == juce::Slider::SliderStyle::ThreeValueVertical || style == juce::Slider::SliderStyle::ThreeValueHorizontal);
auto trackWidth = juce::jmin (6.0f, slider.isHorizontal() ? (float) height * 0.25f : (float) width * 0.25f);
juce::Point<float> startPoint (slider.isHorizontal() ? (float) x : (float) x + (float) width * 0.5f,
slider.isHorizontal() ? (float) y + (float) height * 0.5f : (float) (height + y));
juce::Point<float> endPoint (slider.isHorizontal() ? (float) (width + x) : startPoint.x,
slider.isHorizontal() ? startPoint.y : (float) y);
juce::Path backgroundTrack;
backgroundTrack.startNewSubPath (startPoint);
backgroundTrack.lineTo (endPoint);
g.setColour (slider.findColour (juce::Slider::backgroundColourId));
g.strokePath (backgroundTrack, { trackWidth, juce::PathStrokeType::curved, juce::PathStrokeType::rounded });
juce::Path valueTrack;
juce::Point<float> minPoint, maxPoint, thumbPoint;
if (isTwoVal || isThreeVal)
{
minPoint = { slider.isHorizontal() ? minSliderPos : (float) width * 0.5f,
slider.isHorizontal() ? (float) height * 0.5f : minSliderPos };
if (isThreeVal)
thumbPoint = { slider.isHorizontal() ? sliderPos : (float) width * 0.5f,
slider.isHorizontal() ? (float) height * 0.5f : sliderPos };
maxPoint = { slider.isHorizontal() ? maxSliderPos : (float) width * 0.5f,
slider.isHorizontal() ? (float) height * 0.5f : maxSliderPos };
}
else
{
auto kx = slider.isHorizontal() ? sliderPos : ((float) x + (float) width * 0.5f);
auto ky = slider.isHorizontal() ? ((float) y + (float) height * 0.5f) : sliderPos;
minPoint = startPoint;
maxPoint = { kx, ky };
}
auto thumbWidth = getSliderThumbRadius (slider);
valueTrack.startNewSubPath (minPoint);
valueTrack.lineTo (isThreeVal ? thumbPoint : maxPoint);
g.setColour (slider.findColour (juce::Slider::trackColourId).withAlpha(alpha));
g.strokePath (valueTrack, { trackWidth, juce::PathStrokeType::curved, juce::PathStrokeType::rounded });
if (! isTwoVal)
{
g.setColour (slider.findColour (juce::Slider::thumbColourId));
g.fillEllipse (juce::Rectangle<float> (static_cast<float> (thumbWidth), static_cast<float> (thumbWidth)).withCentre (isThreeVal ? thumbPoint : maxPoint));
}
if (isTwoVal || isThreeVal)
{
auto sr = juce::jmin (trackWidth, (slider.isHorizontal() ? (float) height : (float) width) * 0.4f);
auto pointerColour = slider.findColour (juce::Slider::thumbColourId);
if (slider.isHorizontal())
{
drawPointer (g, minSliderPos - sr,
juce::jmax (0.0f, (float) y + (float) height * 0.5f - trackWidth * 2.0f),
trackWidth * 2.0f, pointerColour, 2);
drawPointer (g, maxSliderPos - trackWidth,
juce::jmin ((float) (y + height) - trackWidth * 2.0f, (float) y + (float) height * 0.5f),
trackWidth * 2.0f, pointerColour, 4);
}
else
{
drawPointer (g, juce::jmax (0.0f, (float) x + (float) width * 0.5f - trackWidth * 2.0f),
minSliderPos - trackWidth,
trackWidth * 2.0f, pointerColour, 1);
drawPointer (g, juce::jmin ((float) (x + width) - trackWidth * 2.0f, (float) x + (float) width * 0.5f), maxSliderPos - sr,
trackWidth * 2.0f, pointerColour, 3);
}
}
if (slider.isBar())
drawLinearSliderOutline (g, x, y, width, height, style, slider);
}
auto kx = slider.isHorizontal() ? sliderPos : ((float)x + (float)width * 0.5f);
auto ky = slider.isHorizontal() ? ((float)y + (float)height * 0.5f) : sliderPos;
@ -147,7 +243,7 @@ void OscirenderLookAndFeel::drawLinearSlider(juce::Graphics& g, int x, int y, in
auto thumbWidth = getSliderThumbRadius(slider);
g.setColour(slider.findColour(sliderThumbOutlineColourId));
g.setColour(slider.findColour(sliderThumbOutlineColourId).withAlpha(alpha));
g.drawEllipse(juce::Rectangle<float>(static_cast<float>(thumbWidth), static_cast<float>(thumbWidth)).withCentre(point), 1.0f);
}

Wyświetl plik

@ -41,6 +41,7 @@ void EffectComponent::setupComponent() {
bool enabled = effect.enabled == nullptr || effect.enabled->getValue();
selected.setToggleState(enabled, juce::dontSendNotification);
updateEnabled();
lfoEnabled = parameter->lfo != nullptr && parameter->lfoRate != nullptr;
if (lfoEnabled) {
@ -129,9 +130,12 @@ void EffectComponent::resized() {
auto checkboxLabel = bounds.removeFromLeft(120);
if (checkboxVisible) {
if (checkboxVisible || subParameter) {
checkboxLabel.removeFromLeft(2);
selected.setBounds(checkboxLabel.removeFromLeft(25));
auto checkboxBounds = checkboxLabel.removeFromLeft(25);
if (checkboxVisible) {
selected.setBounds(checkboxBounds);
}
} else {
checkboxLabel.removeFromLeft(5);
}
@ -144,6 +148,10 @@ void EffectComponent::paint(juce::Graphics& g) {
g.fillAll(findColour(effectComponentBackgroundColourId));
g.setColour(juce::Colours::white);
g.drawText(effect.parameters[index]->name, textBounds, juce::Justification::left);
if (!selected.getToggleState()) {
g.setColour(juce::Colours::black.withAlpha(0.5f));
g.fillAll();
}
}
void EffectComponent::mouseDown(const juce::MouseEvent& event) {
@ -181,3 +189,15 @@ void EffectComponent::setComponent(std::shared_ptr<juce::Component> component) {
void EffectComponent::setCheckboxVisible(bool visible) {
checkboxVisible = visible;
}
void EffectComponent::setSubParameter(bool subParameter) {
this->subParameter = subParameter;
}
void EffectComponent::updateEnabled() {
bool enabled = selected.getToggleState();
slider.setEnabled(enabled);
lfoSlider.setEnabled(enabled);
lfo.setEnabled(enabled);
repaint();
}

Wyświetl plik

@ -18,8 +18,10 @@ public:
void parameterValueChanged(int parameterIndex, float newValue) override;
void parameterGestureChanged(int parameterIndex, bool gestureIsStarting) override;
void handleAsyncUpdate() override;
void updateEnabled();
void setCheckboxVisible(bool visible);
void setSubParameter(bool subParameter);
void setComponent(std::shared_ptr<juce::Component> component);
juce::Slider slider;
@ -32,6 +34,7 @@ public:
private:
void setupComponent();
bool checkboxVisible = true;
bool subParameter = false;
bool lfoEnabled = true;
juce::Rectangle<int> textBounds;
std::shared_ptr<juce::Component> component;

Wyświetl plik

@ -21,9 +21,12 @@ EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectList
auto data = (AudioEffectListBoxItemData&)modelData;
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
data.setSelected(rowNum, effectComponent->selected.getToggleState());
effectComponent->updateEnabled();
}
};
}
}
effectComponent->setSubParameter(i != 0);
auto component = createComponent(parameters[i]);
if (component != nullptr) {
@ -34,7 +37,7 @@ EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectList
}
list.setModel(&listModel);
list.setRowHeight(30);
list.setRowHeight(ROW_HEIGHT);
list.updateContent();
addAndMakeVisible(list);
}
@ -43,9 +46,10 @@ EffectsListComponent::~EffectsListComponent() {}
void EffectsListComponent::paint(juce::Graphics& g) {
auto bounds = getLocalBounds();
g.fillAll(findColour(effectComponentHandleColourId));
g.setColour(findColour(effectComponentHandleColourId));
bounds.removeFromBottom(2);
g.fillRect(bounds);
g.setColour(juce::Colours::white);
bounds.removeFromLeft(20);
// draw drag and drop handle using circles
double size = 4;
double leftPad = 4;
@ -61,12 +65,6 @@ void EffectsListComponent::paint(juce::Graphics& g) {
DraggableListBoxItem::paint(g);
}
void EffectsListComponent::paintOverChildren(juce::Graphics& g) {
auto bounds = getLocalBounds();
g.setColour(juce::Colours::white);
g.drawRect(bounds);
}
void EffectsListComponent::resized() {
auto area = getLocalBounds();
area.removeFromLeft(20);
@ -105,7 +103,7 @@ std::shared_ptr<juce::Component> EffectsListComponent::createComponent(EffectPar
int EffectsListBoxModel::getRowHeight(int row) {
auto data = (AudioEffectListBoxItemData&)modelData;
return data.getEffect(row)->parameters.size() * 30;
return data.getEffect(row)->parameters.size() * EffectsListComponent::ROW_HEIGHT + 2;
}
bool EffectsListBoxModel::hasVariableHeightRows() const {

Wyświetl plik

@ -19,12 +19,12 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
}
void resetData() {
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
data.clear();
for (int i = 0; i < audioProcessor.toggleableEffects.size(); i++) {
auto effect = audioProcessor.toggleableEffects[i];
effect->setValue(effect->getValue());
data.push_back(effect);
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
data.clear();
for (int i = 0; i < audioProcessor.toggleableEffects.size(); i++) {
auto effect = audioProcessor.toggleableEffects[i];
effect->setValue(effect->getValue());
data.push_back(effect);
}
}
@ -42,22 +42,22 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
// data.push_back(juce::String("Yahoo"));
}
void moveBefore(int indexOfItemToMove, int indexOfItemToPlaceBefore) override {
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
auto effect = data[indexOfItemToMove];
if (indexOfItemToMove < indexOfItemToPlaceBefore) {
move(data, indexOfItemToMove, indexOfItemToPlaceBefore - 1);
} else {
move(data, indexOfItemToMove, indexOfItemToPlaceBefore);
}
for (int i = 0; i < data.size(); i++) {
data[i]->setPrecedence(i);
}
audioProcessor.updateEffectPrecedence();
void moveBefore(int indexOfItemToMove, int indexOfItemToPlaceBefore) override {
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
auto effect = data[indexOfItemToMove];
if (indexOfItemToMove < indexOfItemToPlaceBefore) {
move(data, indexOfItemToMove, indexOfItemToPlaceBefore - 1);
} else {
move(data, indexOfItemToMove, indexOfItemToPlaceBefore);
}
for (int i = 0; i < data.size(); i++) {
data[i]->setPrecedence(i);
}
audioProcessor.updateEffectPrecedence();
}
void moveAfter(int indexOfItemToMove, int indexOfItemToPlaceAfter) override {
@ -65,25 +65,25 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
auto temp = data[indexOfItemToMove];
if (indexOfItemToMove <= indexOfItemToPlaceAfter) {
move(data, indexOfItemToMove, indexOfItemToPlaceAfter);
} else {
move(data, indexOfItemToMove, indexOfItemToPlaceAfter + 1);
if (indexOfItemToMove <= indexOfItemToPlaceAfter) {
move(data, indexOfItemToMove, indexOfItemToPlaceAfter);
} else {
move(data, indexOfItemToMove, indexOfItemToPlaceAfter + 1);
}
for (int i = 0; i < data.size(); i++) {
data[i]->setPrecedence(i);
for (int i = 0; i < data.size(); i++) {
data[i]->setPrecedence(i);
}
audioProcessor.updateEffectPrecedence();
}
template <typename t> void move(std::vector<t>& v, size_t oldIndex, size_t newIndex) {
if (oldIndex > newIndex) {
std::rotate(v.rend() - oldIndex - 1, v.rend() - oldIndex, v.rend() - newIndex);
} else {
std::rotate(v.begin() + oldIndex, v.begin() + oldIndex + 1, v.begin() + newIndex + 1);
}
template <typename t> void move(std::vector<t>& v, size_t oldIndex, size_t newIndex) {
if (oldIndex > newIndex) {
std::rotate(v.rend() - oldIndex - 1, v.rend() - oldIndex, v.rend() - newIndex);
} else {
std::rotate(v.begin() + oldIndex, v.begin() + oldIndex + 1, v.begin() + newIndex + 1);
}
}
void setSelected(int itemIndex, bool selected) {
@ -107,12 +107,13 @@ public:
~EffectsListComponent();
void paint(juce::Graphics& g) override;
void paintOverChildren(juce::Graphics& g) override;
void resized() override;
static const int ROW_HEIGHT = 30;
protected:
Effect& effect;
ComponentListModel listModel;
Effect& effect;
ComponentListModel listModel;
juce::ListBox list;
private:
OscirenderAudioProcessor& audioProcessor;