Reorder filter dropdown: list LP 48dB below LP 24dB

Keep the parameter choice indices stable (so saved projects, .cfl
files and presets stay correct) and only reorder the displayed menu
via explicit item IDs plus a new IndexedComboBoxAttachment, since the
stock JUCE ComboBoxAttachment hard-maps choice index to menu position.
This commit is contained in:
Armin 2026-08-13 14:55:33 +02:00
commit 45d6082657
2 changed files with 59 additions and 3 deletions

View file

@ -214,9 +214,53 @@ private:
using SliderAttachment = juce::AudioProcessorValueTreeState::SliderAttachment;
using ComboBoxAttachment = juce::AudioProcessorValueTreeState::ComboBoxAttachment;
// Maps a 0-based parameter choice index to a ComboBox itemId (index + 1)
// so the dropdown can be displayed in an order that differs from the
// parameter's index order (e.g. LP 48dB listed under LP 24dB). This keeps
// stored parameter indices meaningful while only reordering the menu.
class IndexedComboBoxAttachment : public juce::AudioProcessorValueTreeState::Listener,
private juce::ComboBox::Listener {
public:
IndexedComboBoxAttachment (juce::AudioProcessorValueTreeState& stateToUse,
const juce::String& paramID,
juce::ComboBox& comboToUse)
: state (stateToUse), paramId (paramID), combo (comboToUse) {
combo.addListener (this);
state.addParameterListener (paramId, this);
auto* p = state.getParameter (paramId);
combo.setSelectedId (1 + juce::roundToInt (p->getValue() * (combo.getNumItems() - 1)),
juce::dontSendNotification);
}
~IndexedComboBoxAttachment() override {
combo.removeListener (this);
state.removeParameterListener (paramId, this);
}
void parameterChanged (const juce::String& parameterID, float newValue) override {
if (parameterID == paramId)
combo.setSelectedId (1 + juce::roundToInt (newValue * (combo.getNumItems() - 1)),
juce::dontSendNotification);
}
void comboBoxChanged (juce::ComboBox* cb) override {
if (cb != &combo)
return;
auto* p = state.getParameter (paramId);
int index = combo.getSelectedId() - 1;
p->setValueNotifyingHost (static_cast<float> (index) / (combo.getNumItems() - 1));
}
private:
juce::AudioProcessorValueTreeState& state;
juce::String paramId;
juce::ComboBox& combo;
};
std::unique_ptr<SliderAttachment> osc1OctAttach, osc1SemiAttach, osc1FineAttach, osc1LevelAttach;
std::unique_ptr<SliderAttachment> osc2OctAttach, osc2SemiAttach, osc2FineAttach, osc2LevelAttach, phaseOffsetAttach;
std::unique_ptr<ComboBoxAttachment> osc1WaveAttach, osc2WaveAttach, filterTypeAttach;
std::unique_ptr<ComboBoxAttachment> osc1WaveAttach, osc2WaveAttach;
std::unique_ptr<IndexedComboBoxAttachment> filterTypeAttach;
std::unique_ptr<ComboBoxAttachment> octaveTransposeAttach, semitoneTransposeAttach;
std::unique_ptr<SliderAttachment> filterCutoffAttach, filterResAttach, filterEnvAmtAttach, keyTrackAttach;
std::unique_ptr<SliderAttachment> envAttackAttach, envDecayAttach, envSustainAttach, envReleaseAttach;