mirror of
https://codeberg.org/armin/chromaflock.git
synced 2026-09-01 04:10:47 +02:00
Make patch LCD clickable to open .cfl load/save file menu
This commit is contained in:
parent
0e9a90a89b
commit
fcdb1939ee
2 changed files with 107 additions and 0 deletions
|
|
@ -529,6 +529,7 @@ MainContentComponent::MainContentComponent(ChromaFlockProcessor& p)
|
||||||
addAndMakeVisible(presetButton);
|
addAndMakeVisible(presetButton);
|
||||||
|
|
||||||
addAndMakeVisible(patchLCD);
|
addAndMakeVisible(patchLCD);
|
||||||
|
patchLCD.onClick = [this]() { showFileMenu(); };
|
||||||
|
|
||||||
auto setupArrow = [&](juce::TextButton& btn) {
|
auto setupArrow = [&](juce::TextButton& btn) {
|
||||||
btn.setColour(juce::TextButton::buttonColourId, juce::Colour(0xcc2a2a2a));
|
btn.setColour(juce::TextButton::buttonColourId, juce::Colour(0xcc2a2a2a));
|
||||||
|
|
@ -703,6 +704,108 @@ void MainContentComponent::showPresetMenu() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainContentComponent::showFileMenu() {
|
||||||
|
juce::PopupMenu menu;
|
||||||
|
menu.addItem(1, "Load Preset...");
|
||||||
|
menu.addItem(2, "Save Preset...");
|
||||||
|
menu.showMenuAsync(juce::PopupMenu::Options().withTargetComponent(&patchLCD),
|
||||||
|
[this](int result) {
|
||||||
|
if (result == 1) loadPresetFile();
|
||||||
|
else if (result == 2) savePresetFile();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* kCflTag = "ChromaFlockPatch";
|
||||||
|
#include "Version.h"
|
||||||
|
static const juce::String kCflVersion = CHROMAFLOCK_VERSION;
|
||||||
|
|
||||||
|
juce::String MainContentComponent::currentPresetName() const {
|
||||||
|
auto& presets = processorRef.presetManager.getPresets();
|
||||||
|
if (currentPresetIndex >= 0 && currentPresetIndex < static_cast<int>(presets.size()))
|
||||||
|
return presets[currentPresetIndex].name;
|
||||||
|
return patchLCD.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainContentComponent::savePresetFile() {
|
||||||
|
auto* chooser = new juce::FileChooser("Save ChromaFlock Preset",
|
||||||
|
juce::File::getSpecialLocation(juce::File::userHomeDirectory)
|
||||||
|
.getChildFile("chromaflock-" + currentPresetName().replaceCharacter(' ', '-') + ".cfl"),
|
||||||
|
"*.cfl");
|
||||||
|
|
||||||
|
chooser->launchAsync(juce::FileBrowserComponent::saveMode
|
||||||
|
| juce::FileBrowserComponent::canSelectFiles,
|
||||||
|
[this, chooser](const juce::FileChooser& c) {
|
||||||
|
std::unique_ptr<juce::FileChooser> deleter(chooser);
|
||||||
|
auto file = c.getResult();
|
||||||
|
if (file == juce::File())
|
||||||
|
return;
|
||||||
|
if (file.getFileExtension().toLowerCase() != ".cfl")
|
||||||
|
file = file.withFileExtension(".cfl");
|
||||||
|
|
||||||
|
auto state = processorRef.apvts.copyState();
|
||||||
|
std::unique_ptr<juce::XmlElement> presetXml(state.createXml());
|
||||||
|
|
||||||
|
std::unique_ptr<juce::XmlElement> root(new juce::XmlElement(kCflTag));
|
||||||
|
root->setAttribute("version", kCflVersion);
|
||||||
|
root->setAttribute("generator", "ChromaFlock");
|
||||||
|
root->addChildElement(presetXml.release());
|
||||||
|
|
||||||
|
if (!root->writeTo(file))
|
||||||
|
juce::NativeMessageBox::showMessageBoxAsync(juce::AlertWindow::WarningIcon,
|
||||||
|
"Save Failed", "Could not write preset file:\n" + file.getFullPathName(), this);
|
||||||
|
else
|
||||||
|
patchLCD.setText(file.getFileNameWithoutExtension());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainContentComponent::loadPresetFile() {
|
||||||
|
auto* chooser = new juce::FileChooser("Load ChromaFlock Preset",
|
||||||
|
juce::File::getSpecialLocation(juce::File::userHomeDirectory),
|
||||||
|
"*.cfl");
|
||||||
|
|
||||||
|
chooser->launchAsync(juce::FileBrowserComponent::openMode
|
||||||
|
| juce::FileBrowserComponent::canSelectFiles,
|
||||||
|
[this, chooser](const juce::FileChooser& c) {
|
||||||
|
std::unique_ptr<juce::FileChooser> deleter(chooser);
|
||||||
|
auto file = c.getResult();
|
||||||
|
if (file == juce::File() || !file.existsAsFile())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::unique_ptr<juce::XmlElement> root(juce::XmlDocument::parse(file));
|
||||||
|
if (root == nullptr || !root->hasTagName(kCflTag)) {
|
||||||
|
juce::NativeMessageBox::showMessageBoxAsync(juce::AlertWindow::WarningIcon,
|
||||||
|
"Invalid File", "This is not a valid ChromaFlock (.cfl) preset file.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fileVersion = root->getStringAttribute("version", "");
|
||||||
|
if (fileVersion != kCflVersion) {
|
||||||
|
juce::NativeMessageBox::showMessageBoxAsync(juce::AlertWindow::WarningIcon,
|
||||||
|
"Version Mismatch",
|
||||||
|
"This preset was saved with ChromaFlock " + (fileVersion.isEmpty() ? "<unknown>" : fileVersion) +
|
||||||
|
", but you are running ChromaFlock " + kCflVersion +
|
||||||
|
".\nThe preset may not sound as intended.", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* presetXml = root->getChildByName(processorRef.apvts.state.getType());
|
||||||
|
if (presetXml == nullptr) {
|
||||||
|
juce::NativeMessageBox::showMessageBoxAsync(juce::AlertWindow::WarningIcon,
|
||||||
|
"Invalid File", "The preset file does not contain ChromaFlock parameter data.", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
processorRef.fadeOutActiveVoices(0.25f);
|
||||||
|
processorRef.apvts.replaceState(juce::ValueTree::fromXml(*presetXml));
|
||||||
|
|
||||||
|
currentPresetIndex = -1;
|
||||||
|
patchLCD.setText(file.getFileNameWithoutExtension());
|
||||||
|
|
||||||
|
setupSyncKnob(lfo1RateKnob, lfo1RateAttach, lfo1BeatAttach, "lfo1Rate", "lfo1Beat", lfo1SyncBox);
|
||||||
|
setupSyncKnob(lfo2RateKnob, lfo2RateAttach, lfo2BeatAttach, "lfo2Rate", "lfo2Beat", lfo2SyncBox);
|
||||||
|
setupSyncKnob(delayTimeKnob, delayTimeAttach, delayBeatAttach, "delayTime", "delayBeat", delaySyncBox);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void MainContentComponent::applyCurrentPreset() {
|
void MainContentComponent::applyCurrentPreset() {
|
||||||
auto& presets = processorRef.presetManager.getPresets();
|
auto& presets = processorRef.presetManager.getPresets();
|
||||||
if (presets.empty()) return;
|
if (presets.empty()) return;
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,10 @@ private:
|
||||||
const juce::String& beatId,
|
const juce::String& beatId,
|
||||||
juce::ComboBox& syncBox);
|
juce::ComboBox& syncBox);
|
||||||
void showPresetMenu();
|
void showPresetMenu();
|
||||||
|
void showFileMenu();
|
||||||
|
void loadPresetFile();
|
||||||
|
void savePresetFile();
|
||||||
|
juce::String currentPresetName() const;
|
||||||
void applyCurrentPreset();
|
void applyCurrentPreset();
|
||||||
void randomizeParameters();
|
void randomizeParameters();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue