Add toggle to disable preview on hover

pull/307/head
James H Ball 2025-08-11 20:29:31 +01:00
rodzic e4261f5ebe
commit 600d69e568
4 zmienionych plików z 55 dodań i 14 usunięć

Wyświetl plik

@ -62,12 +62,16 @@ void EffectTypeGridComponent::setupEffectItems()
};
// Hover preview: request temporary preview of this effect while hovered
item->onHoverStart = [this](const juce::String& effectId) {
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
audioProcessor.setPreviewEffectId(effectId);
if (audioProcessor.getGlobalBoolValue("previewEffectOnHover", true)) {
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
audioProcessor.setPreviewEffectId(effectId);
}
};
item->onHoverEnd = [this]() {
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
audioProcessor.clearPreviewEffect();
if (audioProcessor.getGlobalBoolValue("previewEffectOnHover", true)) {
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
audioProcessor.clearPreviewEffect();
}
};
effectItems.add(item);

Wyświetl plik

@ -6,12 +6,17 @@ MainMenuBarModel::~MainMenuBarModel() {}
void MainMenuBarModel::addTopLevelMenu(const juce::String& name) {
topLevelMenuNames.add(name);
menuItems.push_back(std::vector<std::pair<juce::String, std::function<void()>>>());
menuItems.push_back({});
menuItemsChanged();
}
void MainMenuBarModel::addMenuItem(int topLevelMenuIndex, const juce::String& name, std::function<void()> action) {
menuItems[topLevelMenuIndex].push_back(std::make_pair(name, action));
menuItems[topLevelMenuIndex].push_back({ name, std::move(action), {}, false });
menuItemsChanged();
}
void MainMenuBarModel::addToggleMenuItem(int topLevelMenuIndex, const juce::String& name, std::function<void()> action, std::function<bool()> isTicked) {
menuItems[topLevelMenuIndex].push_back({ name, std::move(action), std::move(isTicked), true });
menuItemsChanged();
}
@ -26,8 +31,13 @@ juce::PopupMenu MainMenuBarModel::getMenuForIndex(int topLevelMenuIndex, const j
customMenuLogic(menu, topLevelMenuIndex);
}
for (int i = 0; i < menuItems[topLevelMenuIndex].size(); i++) {
menu.addItem(i + 1, menuItems[topLevelMenuIndex][i].first);
for (int i = 0; i < (int) menuItems[topLevelMenuIndex].size(); i++) {
auto& mi = menuItems[topLevelMenuIndex][i];
juce::PopupMenu::Item item(mi.name);
item.itemID = i + 1;
if (mi.hasTick && mi.isTicked)
item.setTicked(mi.isTicked());
menu.addItem(item);
}
return menu;
@ -37,7 +47,9 @@ void MainMenuBarModel::menuItemSelected(int menuItemID, int topLevelMenuIndex) {
if (customMenuSelectedLogic && customMenuSelectedLogic(menuItemID, topLevelMenuIndex)) {
return;
}
menuItems[topLevelMenuIndex][menuItemID - 1].second();
auto& mi = menuItems[topLevelMenuIndex][menuItemID - 1];
if (mi.action)
mi.action();
}
void MainMenuBarModel::menuBarActivated(bool isActive) {}

Wyświetl plik

@ -8,6 +8,8 @@ public:
void addTopLevelMenu(const juce::String& name);
void addMenuItem(int topLevelMenuIndex, const juce::String& name, std::function<void()> action);
// Adds a toggle (ticked) menu item whose tick state is provided dynamically via isTicked()
void addToggleMenuItem(int topLevelMenuIndex, const juce::String& name, std::function<void()> action, std::function<bool()> isTicked);
void resetMenuItems();
std::function<void(juce::PopupMenu&, int)> customMenuLogic;
@ -19,6 +21,14 @@ private:
void menuItemSelected(int menuItemID, int topLevelMenuIndex) override;
void menuBarActivated(bool isActive);
struct MenuItem
{
juce::String name;
std::function<void()> action;
std::function<bool()> isTicked; // optional tick state
bool hasTick = false;
};
juce::StringArray topLevelMenuNames;
std::vector<std::vector<std::pair<juce::String, std::function<void()>>>> menuItems;
std::vector<std::vector<MenuItem>> menuItems;
};

Wyświetl plik

@ -10,12 +10,13 @@ OsciMainMenuBarModel::OsciMainMenuBarModel(OscirenderAudioProcessor& p, Oscirend
void OsciMainMenuBarModel::resetMenuItems() {
MainMenuBarModel::resetMenuItems();
addTopLevelMenu("File");
addTopLevelMenu("About");
addTopLevelMenu("Video");
addTopLevelMenu("File"); // index 0
addTopLevelMenu("About"); // index 1
addTopLevelMenu("Video"); // index 2
if (editor.processor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone) {
addTopLevelMenu("Audio");
addTopLevelMenu("Audio"); // index 3 (only if standalone)
}
addTopLevelMenu("Interface"); // index 3 (if not standalone) or 4 (if standalone)
addMenuItem(0, "Open Project", [this] { editor.openProject(); });
addMenuItem(0, "Save Project", [this] { editor.saveProject(); });
@ -88,6 +89,20 @@ void OsciMainMenuBarModel::resetMenuItems() {
editor.openAudioSettings();
});
}
// Interface menu index depends on whether Audio menu exists
int interfaceMenuIndex = (editor.processor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone) ? 4 : 3;
addToggleMenuItem(interfaceMenuIndex, "Preview effect on hover", [this] {
bool current = audioProcessor.getGlobalBoolValue("previewEffectOnHover", true);
bool newValue = ! current;
audioProcessor.setGlobalValue("previewEffectOnHover", newValue);
audioProcessor.saveGlobalSettings();
if (! newValue) {
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
audioProcessor.clearPreviewEffect();
}
resetMenuItems(); // update tick state
}, [this] { return audioProcessor.getGlobalBoolValue("previewEffectOnHover", true); });
}
#if (JUCE_MAC || JUCE_WINDOWS) && OSCI_PREMIUM