add bypass toggle switch UI to top-left

This commit is contained in:
Armin 2026-07-13 01:44:13 +02:00
commit 9d0da19f48
2 changed files with 294 additions and 50 deletions

View file

@ -13,11 +13,12 @@ public:
void resized() override;
void timerCallback() override;
void comboBoxChanged(juce::ComboBox* box) override;
void mouseUp(const juce::MouseEvent& event) override;
private:
SaftpumpeProcessor& processorRef;
float uiScale = 1.5f;
float uiScale = 1.0f;
// Dark industrial palette
juce::Colour bezelColour{0xff0a0a0c};
@ -51,11 +52,16 @@ private:
juce::ComboBox presetBox;
juce::Label presetLabel;
juce::ToggleButton bypassButton;
juce::Label bypassLabel;
using SliderAttachment = juce::AudioProcessorValueTreeState::SliderAttachment;
using ButtonAttachment = juce::AudioProcessorValueTreeState::ButtonAttachment;
std::unique_ptr<SliderAttachment> thresholdAttachment, ratioAttachment, attackAttachment;
std::unique_ptr<SliderAttachment> releaseAttachment, kneeAttachment, makeupAttachment;
std::unique_ptr<SliderAttachment> mixAttachment, autoReleaseAttachment;
std::unique_ptr<ButtonAttachment> bypassAttachment;
juce::Rectangle<float> meterArea;
juce::Rectangle<float> scopeArea;
@ -80,6 +86,7 @@ private:
void drawPeakHold(juce::Graphics& g, juce::Rectangle<float> bounds,
float peakNorm, bool fromTop = false);
void drawScope(juce::Graphics& g, juce::Rectangle<float> bounds);
void drawSpectrum(juce::Graphics& g, juce::Rectangle<float> bounds);
void drawScrew(juce::Graphics& g, float cx, float cy, float radius);
static constexpr float startAngle = juce::MathConstants<float>::pi * 0.75f;
@ -95,11 +102,58 @@ private:
void applyPreset(int index);
juce::Rectangle<float> presetArea;
juce::Rectangle<float> bypassArea;
struct NoDotLookAndFeel : juce::LookAndFeel_V4 {
void drawRotarySlider(juce::Graphics&, int, int, int, int,
float, float, float, juce::Slider&) override {}
} lnf;
struct ToggleSwitchLNF : juce::LookAndFeel_V4 {
void drawToggleButton(juce::Graphics& g, juce::ToggleButton& btn,
bool hover, bool /*isDown*/) override {
auto bounds = btn.getLocalBounds().toFloat();
float s = bounds.getHeight() / 16.0f;
float w = bounds.getWidth();
float h = bounds.getHeight();
float cornerR = h * 0.3f;
// Groove
g.setColour(juce::Colour(0xff111114));
g.fillRoundedRectangle(bounds, cornerR);
g.setColour(juce::Colours::black.withAlpha(0.5f));
g.drawRoundedRectangle(bounds.expanded(0.5f), cornerR, 1.0f);
// Slider handle
bool on = btn.getToggleState();
float handleW = w * 0.42f;
float handleH = h * 0.72f;
float handleX = on ? (bounds.getRight() - handleW - 3.0f * s) : (bounds.getX() + 3.0f * s);
float handleY = bounds.getY() + (h - handleH) / 2.0f;
auto handleBounds = juce::Rectangle<float>(handleX, handleY, handleW, handleH);
// Handle shadow
g.setColour(juce::Colours::black.withAlpha(0.4f));
g.fillRoundedRectangle(handleBounds.translated(0, 1.0f), cornerR * 0.6f);
// Handle body
juce::Colour handleCol = on ? juce::Colour(0xff00e676) : juce::Colour(0xff4a4a50);
if (hover) handleCol = handleCol.brighter(0.15f);
g.setColour(handleCol);
g.fillRoundedRectangle(handleBounds, cornerR * 0.6f);
// Handle highlight
g.setColour(juce::Colours::white.withAlpha(on ? 0.2f : 0.08f));
g.fillRoundedRectangle(handleBounds.withHeight(handleH * 0.4f).translated(0, 1.0f), cornerR * 0.4f);
// LED glow when bypass active
if (on) {
g.setColour(juce::Colour(0xff00e676).withAlpha(0.15f));
g.fillEllipse(bounds.getCentreX() - w * 0.5f, bounds.getCentreY() - h * 0.6f,
w * 1.0f, h * 1.2f);
}
}
} toggleLnf;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SaftpumpeEditor)
};