feat: Highlight main menu item when using a shortcut
This commit is contained in:
parent
0a55f4bf83
commit
6a3b10111f
@ -194,10 +194,12 @@ namespace hex {
|
||||
class ShortcutManager {
|
||||
public:
|
||||
using Callback = std::function<void()>;
|
||||
using EnabledCallback = std::function<bool()>;
|
||||
struct ShortcutEntry {
|
||||
Shortcut shortcut;
|
||||
std::vector<UnlocalizedString> unlocalizedName;
|
||||
Callback callback;
|
||||
EnabledCallback enabledCallback;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -205,9 +207,10 @@ namespace hex {
|
||||
* @param shortcut The shortcut to add.
|
||||
* @param unlocalizedName The unlocalized name of the shortcut
|
||||
* @param callback The callback to call when the shortcut is triggered.
|
||||
* @param enabledCallback Callback that's called to check if this shortcut is enabled
|
||||
*/
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback);
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
|
||||
/**
|
||||
* @brief Add a view-specific shortcut. View-specific shortcuts can only be triggered when the specified view is focused.
|
||||
@ -215,9 +218,10 @@ namespace hex {
|
||||
* @param shortcut The shortcut to add.
|
||||
* @param unlocalizedName The unlocalized name of the shortcut
|
||||
* @param callback The callback to call when the shortcut is triggered.
|
||||
* @param enabledCallback Callback that's called to check if this shortcut is enabled
|
||||
*/
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback);
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
|
||||
|
||||
/**
|
||||
@ -252,6 +256,9 @@ namespace hex {
|
||||
|
||||
static void enableMacOSMode();
|
||||
|
||||
[[nodiscard]] static std::optional<UnlocalizedString> getLastActivatedMenu();
|
||||
static void resetLastActivatedMenu();
|
||||
|
||||
[[nodiscard]] static std::optional<Shortcut> getPreviousShortcut();
|
||||
|
||||
[[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts();
|
||||
|
@ -933,17 +933,10 @@ namespace hex {
|
||||
});
|
||||
|
||||
if (shortcut != Shortcut::None) {
|
||||
auto callbackIfEnabled = [enabledCallback, function]{ if (enabledCallback()) { function(); } };
|
||||
|
||||
const auto unlocalizedShortcutName =
|
||||
unlocalizedMainMenuNames.size() == 1 ?
|
||||
std::vector { unlocalizedMainMenuNames.back() } :
|
||||
std::vector(unlocalizedMainMenuNames.begin() + 1, unlocalizedMainMenuNames.end());
|
||||
|
||||
if (shortcut.isLocal() && view != nullptr)
|
||||
ShortcutManager::addShortcut(view, shortcut, unlocalizedShortcutName, callbackIfEnabled);
|
||||
ShortcutManager::addShortcut(view, shortcut, unlocalizedMainMenuNames, function, enabledCallback);
|
||||
else
|
||||
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedShortcutName, callbackIfEnabled);
|
||||
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedMainMenuNames, function, enabledCallback);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <hex/api/shortcut_manager.hpp>
|
||||
#include <imgui.h>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/helpers/auto_reset.hpp>
|
||||
|
||||
#include <hex/ui/view.hpp>
|
||||
@ -13,6 +14,7 @@ namespace hex {
|
||||
std::atomic<bool> s_paused;
|
||||
std::optional<Shortcut> s_prevShortcut;
|
||||
bool s_macOSMode = false;
|
||||
AutoReset<std::optional<UnlocalizedString>> s_lastShortcutMainMenu;
|
||||
|
||||
}
|
||||
|
||||
@ -232,27 +234,27 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback) {
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback } });
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback, enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback) {
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback } });
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback, enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback) {
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback } });
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback, enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback) {
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback } });
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback, enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
@ -285,7 +287,14 @@ namespace hex {
|
||||
|
||||
if (auto it = shortcuts.find(shortcut); it != shortcuts.end()) {
|
||||
const auto &[foundShortcut, entry] = *it;
|
||||
entry.callback();
|
||||
|
||||
if (entry.enabledCallback()) {
|
||||
entry.callback();
|
||||
|
||||
if (!entry.unlocalizedName.empty()) {
|
||||
s_lastShortcutMainMenu = entry.unlocalizedName.front();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -305,6 +314,15 @@ namespace hex {
|
||||
processShortcut(pressedShortcut, s_globalShortcuts);
|
||||
}
|
||||
|
||||
std::optional<UnlocalizedString> ShortcutManager::getLastActivatedMenu() {
|
||||
return *s_lastShortcutMainMenu;
|
||||
}
|
||||
|
||||
void ShortcutManager::resetLastActivatedMenu() {
|
||||
s_lastShortcutMainMenu->reset();
|
||||
}
|
||||
|
||||
|
||||
void ShortcutManager::clearShortcuts() {
|
||||
s_globalShortcuts->clear();
|
||||
}
|
||||
|
@ -591,6 +591,8 @@ namespace hex {
|
||||
void Window::frame() {
|
||||
auto &io = ImGui::GetIO();
|
||||
|
||||
ShortcutManager::resetLastActivatedMenu();
|
||||
|
||||
// Loop through all views and draw them
|
||||
for (auto &[name, view] : ContentRegistry::Views::impl::getEntries()) {
|
||||
ImGui::GetCurrentContext()->NextWindowData.ClearFlags();
|
||||
|
@ -503,6 +503,7 @@
|
||||
"hex.builtin.setting.interface.native_window_decorations": "Use OS Window decorations",
|
||||
"hex.builtin.setting.interface.color": "Color theme",
|
||||
"hex.builtin.setting.interface.crisp_scaling": "Enable crisp scaling",
|
||||
"hex.builtin.setting.interface.display_shortcut_highlights": "Highlight menu when using shortcuts",
|
||||
"hex.builtin.setting.interface.fps": "FPS Limit",
|
||||
"hex.builtin.setting.interface.fps.unlocked": "Unlocked",
|
||||
"hex.builtin.setting.interface.fps.native": "Native",
|
||||
|
@ -302,7 +302,8 @@ namespace hex::plugin::builtin {
|
||||
ImGui::SameLine();
|
||||
|
||||
std::string fullName;
|
||||
for (const auto &part : m_fullName) {
|
||||
for (u32 i = m_fullName.size() == 1 ? 0 : 1; i < m_fullName.size(); i += 1) {
|
||||
const auto &part = m_fullName[i];
|
||||
fullName += Lang(part).get();
|
||||
fullName += " -> ";
|
||||
}
|
||||
@ -804,6 +805,7 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.pattern_data_row_bg", false);
|
||||
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.always_show_provider_tabs", false);
|
||||
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.show_header_command_palette", true);
|
||||
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.display_shortcut_highlights", true);
|
||||
|
||||
std::vector<std::string> languageNames;
|
||||
std::vector<nlohmann::json> languageCodes;
|
||||
@ -957,14 +959,28 @@ namespace hex::plugin::builtin {
|
||||
|
||||
/* Shorcuts */
|
||||
{
|
||||
EventImHexStartupFinished::subscribe([]{
|
||||
EventImHexStartupFinished::subscribe([] {
|
||||
for (const auto &shortcutEntry : ShortcutManager::getGlobalShortcuts()) {
|
||||
ContentRegistry::Settings::add<KeybindingWidget>("hex.builtin.setting.shortcuts", "hex.builtin.setting.shortcuts.global", shortcutEntry.unlocalizedName.back(), nullptr, shortcutEntry.shortcut, shortcutEntry.unlocalizedName);
|
||||
ContentRegistry::Settings::add<KeybindingWidget>(
|
||||
"hex.builtin.setting.shortcuts",
|
||||
"hex.builtin.setting.shortcuts.global",
|
||||
shortcutEntry.unlocalizedName.back(),
|
||||
nullptr,
|
||||
shortcutEntry.shortcut,
|
||||
shortcutEntry.unlocalizedName
|
||||
);
|
||||
}
|
||||
|
||||
for (auto &[viewName, view] : ContentRegistry::Views::impl::getEntries()) {
|
||||
for (const auto &shortcutEntry : ShortcutManager::getViewShortcuts(view.get())) {
|
||||
ContentRegistry::Settings::add<KeybindingWidget>("hex.builtin.setting.shortcuts", viewName, shortcutEntry.unlocalizedName.back(), view.get(), shortcutEntry.shortcut, shortcutEntry.unlocalizedName);
|
||||
ContentRegistry::Settings::add<KeybindingWidget>(
|
||||
"hex.builtin.setting.shortcuts",
|
||||
viewName,
|
||||
shortcutEntry.unlocalizedName.back(),
|
||||
view.get(),
|
||||
shortcutEntry.shortcut,
|
||||
shortcutEntry.unlocalizedName
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -26,6 +26,7 @@ namespace hex::plugin::builtin {
|
||||
u32 s_searchBarPosition = 0;
|
||||
ImGuiExt::Texture s_logoTexture;
|
||||
bool s_showSearchBar = true;
|
||||
bool s_displayShortcutHighlights = true;
|
||||
|
||||
void createNestedMenu(std::span<const UnlocalizedString> menuItems, const char *icon, const Shortcut &shortcut, const ContentRegistry::Interface::impl::MenuCallback &callback, const ContentRegistry::Interface::impl::EnabledCallback &enabledCallback, const ContentRegistry::Interface::impl::SelectedCallback &selectedCallback) {
|
||||
const auto &name = menuItems.front();
|
||||
@ -287,7 +288,16 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::BeginMenu(Lang(menuName))) {
|
||||
populateMenu(menuName);
|
||||
ImGui::EndMenu();
|
||||
} else {
|
||||
if (s_displayShortcutHighlights) {
|
||||
if (const auto lastShortcutMenu = ShortcutManager::getLastActivatedMenu(); lastShortcutMenu.has_value()) {
|
||||
if (menuName == *lastShortcutMenu) {
|
||||
ImGui::NavHighlightActivated(ImGui::GetItemID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void drawMenu() {
|
||||
@ -588,6 +598,10 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::Settings::onChange("hex.builtin.setting.interface", "hex.builtin.setting.interface.show_header_command_palette", [](const ContentRegistry::Settings::SettingsValue &value) {
|
||||
s_showSearchBar = value.get<bool>(true);
|
||||
});
|
||||
|
||||
ContentRegistry::Settings::onChange("hex.builtin.setting.interface", "hex.builtin.setting.interface.display_shortcut_highlights", [](const ContentRegistry::Settings::SettingsValue &value) {
|
||||
s_displayShortcutHighlights = value.get<bool>(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user