Reduce plugin width by 102px and fix bottom panel layout to scale proportionally

This commit is contained in:
Armin 2026-07-22 23:10:55 +02:00
commit f035e89ba9
9 changed files with 305 additions and 106 deletions

View file

@ -3,9 +3,11 @@
MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
: AudioProcessorEditor(p),
processorRef(p),
waveformDisplay(p.getSliceManager())
waveformDisplay(p.getSliceManager()),
vuMeter(p)
{
setSize(baseWidth, baseHeight);
setLookAndFeel(&lnf);
// Title bar buttons
auto setupTitleBtn = [this](juce::Button& btn, const juce::String& tip) {
@ -13,6 +15,7 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
btn.addListener(this);
btn.setTooltip(tip);
btn.setColour(juce::TextButton::buttonColourId, juce::Colour(0xff2a2a4a));
btn.setColour(juce::TextButton::textColourOffId, juce::Colours::white);
};
setupTitleBtn(loadSampleButton, "Load audio file");
@ -36,6 +39,10 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
scaleComboBox.addItem("200%", 6);
scaleComboBox.addListener(this);
scaleComboBox.setTooltip("UI Scale");
scaleComboBox.setColour(juce::ComboBox::backgroundColourId, juce::Colour(0xff2a2a4a));
scaleComboBox.setColour(juce::ComboBox::textColourId, juce::Colours::white);
scaleComboBox.setColour(juce::ComboBox::outlineColourId, juce::Colour(0xff444466));
scaleComboBox.setColour(juce::ComboBox::arrowColourId, juce::Colours::white);
scaleAttachment = std::make_unique<ComboBoxAttachment>(processorRef.getAPVTS(), "uiScale", scaleComboBox);
addAndMakeVisible(octaveComboBox);
@ -52,9 +59,13 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
// Bottom panel buttons
addAndMakeVisible(autoSliceButton);
autoSliceButton.addListener(this);
autoSliceButton.setColour(juce::TextButton::buttonColourId, juce::Colour(0xff2a2a4a));
autoSliceButton.setColour(juce::TextButton::textColourOffId, juce::Colours::white);
addAndMakeVisible(clearSlicesButton);
clearSlicesButton.addListener(this);
clearSlicesButton.setColour(juce::TextButton::buttonColourId, juce::Colour(0xff2a2a4a));
clearSlicesButton.setColour(juce::TextButton::textColourOffId, juce::Colours::white);
addAndMakeVisible(waveformDisplay);
// Status bar labels
@ -103,6 +114,12 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
filterTypeComboBox.setColour(juce::ComboBox::outlineColourId, juce::Colour(0xff444466));
filterTypeComboBox.setColour(juce::ComboBox::arrowColourId, juce::Colours::white);
addAndMakeVisible(filterTypeLabel);
filterTypeLabel.setText("Filter Type", juce::dontSendNotification);
filterTypeLabel.setJustificationType(juce::Justification::centred);
filterTypeLabel.setFont(juce::Font(juce::FontOptions(13.0f)));
filterTypeLabel.attachToComponent(&filterTypeComboBox, false);
// Filter ADSR
attachSlider(filterAttackSlider, filterAttackLabel, "F Atk", "filterAttack", filterAttackAttachment);
attachSlider(filterDecaySlider, filterDecayLabel, "F Dcy", "filterDecay", filterDecayAttachment);
@ -115,7 +132,7 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
bpmSlider.setTextBoxStyle(juce::Slider::TextBoxLeft, false, 50, 20);
bpmSlider.setRange(20.0, 300.0, 1.0);
bpmSlider.setColour(juce::Slider::thumbColourId, juce::Colours::transparentBlack);
bpmSlider.setColour(juce::Slider::rotarySliderFillColourId, juce::Colour(0xffee8833));
bpmSlider.setColour(juce::Slider::rotarySliderFillColourId, juce::Colour(0xff3a73e5));
bpmSlider.setColour(juce::Slider::textBoxTextColourId, juce::Colours::white);
bpmSlider.setColour(juce::Slider::textBoxBackgroundColourId, juce::Colour(0xff2a2a4a));
bpmSlider.setColour(juce::Slider::textBoxOutlineColourId, juce::Colour(0xff444466));
@ -140,6 +157,7 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
addAndMakeVisible(stretchButton);
stretchButton.addListener(this);
stretchButton.setColour(juce::TextButton::buttonColourId, juce::Colour(0xff2a2a4a));
stretchButton.setColour(juce::TextButton::textColourOffId, juce::Colours::white);
// Key shift combo
addAndMakeVisible(keyShiftComboBox);
@ -157,6 +175,8 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
keyShiftLabel.attachToComponent(&keyShiftComboBox, false);
keyShiftAttachment = std::make_unique<ComboBoxAttachment>(processorRef.getAPVTS(), "keyShift", keyShiftComboBox);
addAndMakeVisible(vuMeter);
auto allKnobs = { &bassSlider, &trebleSlider, &sensitivitySlider,
&ampAttackSlider, &ampDecaySlider, &ampSustainSlider, &ampReleaseSlider,
&filterCutoffSlider, &filterResoSlider, &filterEnvDepthSlider,
@ -167,8 +187,8 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
slider->setSliderStyle(juce::Slider::RotaryVerticalDrag);
slider->setTextBoxStyle(juce::Slider::TextBoxBelow, false, 40, 14);
slider->setColour(juce::Slider::thumbColourId, juce::Colours::transparentBlack);
slider->setColour(juce::Slider::rotarySliderFillColourId, juce::Colour(0xffee8833));
slider->setColour(juce::Slider::rotarySliderOutlineColourId, juce::Colour(0xff332211));
slider->setColour(juce::Slider::rotarySliderFillColourId, juce::Colour(0xff3a73e5));
slider->setColour(juce::Slider::rotarySliderOutlineColourId, juce::Colour(0xff1a192d));
}
if (processorRef.getSampleBuffer().getNumSamples() > 0)
@ -182,12 +202,11 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
waveformDisplay.setOnKeyClick([this](int midiNote) {
keyClickNote = midiNote;
int pitchClass = midiNote % 12;
int sliceIdx = -1;
const auto& slices = processorRef.getSliceManager().getSlices();
for (int i = 0; i < static_cast<int>(slices.size()); ++i)
{
if (slices[static_cast<size_t>(i)].midiNote == pitchClass)
if (slices[static_cast<size_t>(i)].midiNote == midiNote)
{
sliceIdx = i;
break;
@ -195,8 +214,6 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
}
if (sliceIdx >= 0)
processorRef.triggerSlice(sliceIdx, 0.8f);
else
processorRef.triggerSlice(0, 0.8f);
});
startTimerHz(30);
@ -297,11 +314,23 @@ void MonoslicerEditor::resized()
scaleComboBox.setBounds(titleBar.getRight() - 100, titleBar.getY() + 8, 90, 24);
octaveComboBox.setBounds(titleBar.getRight() - 176, titleBar.getY() + 8, 72, 24);
auto bottomPanel = bounds.removeFromBottom(200);
auto bottomPanel = bounds.removeFromBottom(236);
auto bottomRow = bottomPanel.reduced(8);
bottomRow.removeFromTop(10);
int bw = bottomRow.getWidth();
int sectionGap = 8;
int comboGap = 4;
int contentW = bw - 2 * sectionGap - comboGap;
int leftW = static_cast<int>(contentW * 0.21);
int comboW = static_cast<int>(contentW * 0.12);
int kw = (contentW - leftW - comboW) / 7;
int adsrW = 4 * kw;
int filterW = 3 * kw + comboW + comboGap;
// Bottom panel: buttons + stretch | amp ADSR | filter ADSR | filter knobs
auto leftArea = bottomRow.removeFromLeft(200);
auto leftArea = bottomRow.removeFromLeft(leftW);
{
auto btnArea = leftArea.removeFromTop(28);
autoSliceButton.setBounds(btnArea.getX(), btnArea.getY(), btnArea.getWidth() / 2 - 2, 24);
@ -318,45 +347,39 @@ void MonoslicerEditor::resized()
leftArea.removeFromTop(26);
leftArea.removeFromTop(20);
keyShiftComboBox.setBounds(leftArea.getX(), leftArea.getY(), stretchW, 20);
leftArea.removeFromTop(24);
vuMeter.setBounds(leftArea.getX(), leftArea.getY(), stretchW, 40);
}
bottomRow.removeFromLeft(8);
bottomRow.removeFromLeft(sectionGap);
auto ampSection = bottomRow.removeFromLeft(230);
auto adsrSection = bottomRow.removeFromLeft(adsrW);
{
int kw = ampSection.getWidth() / 4;
int topRowH = 80;
int bottomRowGap = 50;
int bottomRowH = adsrSection.getHeight() - topRowH - bottomRowGap;
int k = 0;
for (auto* s : { &ampAttackSlider, &ampDecaySlider, &ampSustainSlider, &ampReleaseSlider })
{
s->setBounds(ampSection.getX() + k * kw, ampSection.getY(), kw, ampSection.getHeight());
s->setBounds(adsrSection.getX() + k * kw, adsrSection.getY(), kw, topRowH);
++k;
}
}
bottomRow.removeFromLeft(8);
auto fltAdsSection = bottomRow.removeFromLeft(230);
{
int kw = fltAdsSection.getWidth() / 4;
int k = 0;
int bottomY = adsrSection.getY() + topRowH + bottomRowGap;
k = 0;
for (auto* s : { &filterAttackSlider, &filterDecaySlider, &filterSustainSlider, &filterReleaseSlider })
{
s->setBounds(fltAdsSection.getX() + k * kw, fltAdsSection.getY(), kw, fltAdsSection.getHeight());
s->setBounds(adsrSection.getX() + k * kw, bottomY, kw, bottomRowH);
++k;
}
}
bottomRow.removeFromLeft(8);
bottomRow.removeFromLeft(sectionGap);
auto filterArea = bottomRow;
{
int comboW = 56;
int gap = 4;
int knobAreaX = filterArea.getX() + comboW + gap;
int knobAreaW = filterArea.getWidth() - comboW - gap;
int kw = knobAreaW / 3;
int knobAreaX = filterArea.getX() + comboW + comboGap;
int topRowH = 80;
int bottomRowGap = 24;
int bottomRowGap = 50;
int bottomRowH = filterArea.getHeight() - topRowH - bottomRowGap;
filterTypeComboBox.setBounds(filterArea.getX(), filterArea.getY() + 2, comboW, 20);
filterCutoffSlider.setBounds(knobAreaX, filterArea.getY(), kw, topRowH);
@ -389,8 +412,8 @@ void MonoslicerEditor::timerCallback()
/ processorRef.getSampleRateLoaded();
int mins = static_cast<int>(duration) / 60;
int secs = static_cast<int>(duration) % 60;
fileInfoLabel.setButtonText(file.getFileName() + " "
+ juce::String(mins) + ":" + juce::String(secs).paddedLeft('0', 2));
fileInfoLabel.setButtonText("File: " + file.getFileName() + " [Time: "
+ juce::String(mins) + ":" + juce::String(secs).paddedLeft('0', 2) + "]");
}
else
{
@ -458,11 +481,11 @@ void MonoslicerEditor::buttonClicked(juce::Button* button)
}
else if (button == &undoButton)
{
processorRef.getSliceManager().undo();
processorRef.undo();
}
else if (button == &redoButton)
{
processorRef.getSliceManager().redo();
processorRef.redo();
}
else if (button == &stretchButton)
{