diff --git a/source/dsp/controller_attach.cpp b/source/dsp/controller_attach.cpp index 621ee3a..7c031e8 100644 --- a/source/dsp/controller_attach.cpp +++ b/source/dsp/controller_attach.cpp @@ -33,6 +33,7 @@ namespace zlDSP { void ControllerAttach::parameterChanged(const juce::String ¶meterID, float newValue) { if (parameterID == splitType::ID) { + newValue = std::min(newValue, static_cast(splitType::tsteady)); controllerRef.setType(static_cast(newValue)); triggerAsyncUpdate(); } else if (parameterID == mix::ID) { diff --git a/source/dsp/dsp_definitions.hpp b/source/dsp/dsp_definitions.hpp index d39fe94..0555a81 100644 --- a/source/dsp/dsp_definitions.hpp +++ b/source/dsp/dsp_definitions.hpp @@ -73,7 +73,7 @@ namespace zlDSP { auto static constexpr ID = "split_type"; auto static constexpr name = "Split Type"; inline auto static const choices = juce::StringArray{ - "Left Right", "Mid Side", "Low High", "Transient Steady" + "Left Right", "Mid Side", "Low High", "Transient Steady", "", "", "", "" }; int static constexpr defaultI = 0; diff --git a/source/gui/combobox/combobox.hpp b/source/gui/combobox/combobox.hpp index 4b4a6ad..f6b8f8a 100644 --- a/source/gui/combobox/combobox.hpp +++ b/source/gui/combobox/combobox.hpp @@ -14,5 +14,6 @@ #include "compact_figure_combobox/compact_figure_combobox.hpp" #include "left_right_combobox/left_right_combobox.hpp" #include "click_combobox/click_combobox.hpp" +#include "combobox_sub_attachment.hpp" #endif //ZLINTERFACE_COMBOBOX_H diff --git a/source/gui/combobox/combobox_sub_attachment.hpp b/source/gui/combobox/combobox_sub_attachment.hpp new file mode 100644 index 0000000..0fc9b44 --- /dev/null +++ b/source/gui/combobox/combobox_sub_attachment.hpp @@ -0,0 +1,75 @@ +// Copyright (C) 2024 - zsliu98 +// This file is part of ZLSplitter +// +// ZLSplitter is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +// +// ZLSplitter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with ZLSplitter. If not, see . + +#ifndef COMBOBOX_SUB_ATTACHMENT_HPP +#define COMBOBOX_SUB_ATTACHMENT_HPP + +#include +#include + +namespace zlInterface { + class ComboBoxSubAttachment final : private juce::ComboBox::Listener { + public: + ComboBoxSubAttachment(const juce::AudioProcessorValueTreeState &stateToUse, + const juce::String ¶meterID, + juce::ComboBox &combo, + const int numItem) + : comboBox(combo), + storedParameter(*(stateToUse.getParameter(parameterID))), + numItems(numItem), + attachment(*(stateToUse.getParameter(parameterID)), + [this](const float f) { setValue(f); }, + stateToUse.undoManager) { + sendInitialUpdate(); + comboBox.addListener(this); + } + + ~ComboBoxSubAttachment() override { + comboBox.removeListener(this); + } + + /** Call this after setting up your combo box in the case where you need to do + extra setup after constructing this attachment. + */ + void sendInitialUpdate() { + attachment.sendInitialUpdate(); + } + + private: + void setValue(const float newValue) { + const auto normValue = storedParameter.convertTo0to1(newValue); + const auto index = std::min(juce::roundToInt(normValue * static_cast(numItems - 1)), + comboBox.getNumItems() - 1); + + if (index == comboBox.getSelectedItemIndex()) return; + + const juce::ScopedValueSetter svs(ignoreCallbacks, true); + comboBox.setSelectedItemIndex(index, juce::sendNotificationSync); + } + + void comboBoxChanged(juce::ComboBox *) override { + if (ignoreCallbacks) + return; + + const auto selected = static_cast(comboBox.getSelectedItemIndex()); + const auto newValue = numItems > 1 + ? selected / static_cast(numItems - 1) + : 0.0f; + attachment.setValueAsCompleteGesture(storedParameter.convertFrom0to1(newValue)); + } + + juce::ComboBox &comboBox; + juce::RangedAudioParameter &storedParameter; + int numItems; + juce::ParameterAttachment attachment; + bool ignoreCallbacks = false; + }; +} + +#endif //COMBOBOX_SUB_ATTACHMENT_HPP diff --git a/source/panel/top_panel/top_panel.cpp b/source/panel/top_panel/top_panel.cpp index e94dace..2ba963a 100644 --- a/source/panel/top_panel/top_panel.cpp +++ b/source/panel/top_panel/top_panel.cpp @@ -25,10 +25,9 @@ namespace zlPanel { tsIcon(juce::Drawable::createFromImageData(BinaryData::transientsteady_svg, BinaryData::transientsteady_svgSize)), swapButton("", base), - splitBox({lrIcon.get(), msIcon.get(), lhIcon.get(), tsIcon.get()}, base) { + splitBox({lrIcon.get(), msIcon.get(), lhIcon.get(), tsIcon.get()}, base), + boxAttachment(processor.parameters, zlDSP::splitType::ID, splitBox.getBox(), zlDSP::splitType::choices.size()) { attach({&swapButton.getButton()}, {zlDSP::swap::ID}, processor.parameters, buttonAttachments); - attach({&splitBox.getBox()}, {zlDSP::splitType::ID}, processor.parameters, boxAttachments); - addAndMakeVisible(logoPanel); swapButton.getLAF().enableShadow(false); diff --git a/source/panel/top_panel/top_panel.hpp b/source/panel/top_panel/top_panel.hpp index 1438f61..153ef2d 100644 --- a/source/panel/top_panel/top_panel.hpp +++ b/source/panel/top_panel/top_panel.hpp @@ -34,7 +34,7 @@ namespace zlPanel { zlInterface::CompactFigureCombobox splitBox; juce::OwnedArray buttonAttachments; - juce::OwnedArray boxAttachments; + zlInterface::ComboBoxSubAttachment boxAttachment; }; } // zlPanel