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 {
|
class ShortcutManager {
|
||||||
public:
|
public:
|
||||||
using Callback = std::function<void()>;
|
using Callback = std::function<void()>;
|
||||||
|
using EnabledCallback = std::function<bool()>;
|
||||||
struct ShortcutEntry {
|
struct ShortcutEntry {
|
||||||
Shortcut shortcut;
|
Shortcut shortcut;
|
||||||
std::vector<UnlocalizedString> unlocalizedName;
|
std::vector<UnlocalizedString> unlocalizedName;
|
||||||
Callback callback;
|
Callback callback;
|
||||||
|
EnabledCallback enabledCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -205,9 +207,10 @@ namespace hex {
|
|||||||
* @param shortcut The shortcut to add.
|
* @param shortcut The shortcut to add.
|
||||||
* @param unlocalizedName The unlocalized name of the shortcut
|
* @param unlocalizedName The unlocalized name of the shortcut
|
||||||
* @param callback The callback to call when the shortcut is triggered.
|
* @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 std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||||
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
|
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.
|
* @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 shortcut The shortcut to add.
|
||||||
* @param unlocalizedName The unlocalized name of the shortcut
|
* @param unlocalizedName The unlocalized name of the shortcut
|
||||||
* @param callback The callback to call when the shortcut is triggered.
|
* @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 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);
|
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();
|
static void enableMacOSMode();
|
||||||
|
|
||||||
|
[[nodiscard]] static std::optional<UnlocalizedString> getLastActivatedMenu();
|
||||||
|
static void resetLastActivatedMenu();
|
||||||
|
|
||||||
[[nodiscard]] static std::optional<Shortcut> getPreviousShortcut();
|
[[nodiscard]] static std::optional<Shortcut> getPreviousShortcut();
|
||||||
|
|
||||||
[[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts();
|
[[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts();
|
||||||
|
@ -933,17 +933,10 @@ namespace hex {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (shortcut != Shortcut::None) {
|
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)
|
if (shortcut.isLocal() && view != nullptr)
|
||||||
ShortcutManager::addShortcut(view, shortcut, unlocalizedShortcutName, callbackIfEnabled);
|
ShortcutManager::addShortcut(view, shortcut, unlocalizedMainMenuNames, function, enabledCallback);
|
||||||
else
|
else
|
||||||
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedShortcutName, callbackIfEnabled);
|
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedMainMenuNames, function, enabledCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <hex/api/shortcut_manager.hpp>
|
#include <hex/api/shortcut_manager.hpp>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <hex/api/content_registry.hpp>
|
#include <hex/api/content_registry.hpp>
|
||||||
|
#include <hex/api/task_manager.hpp>
|
||||||
#include <hex/helpers/auto_reset.hpp>
|
#include <hex/helpers/auto_reset.hpp>
|
||||||
|
|
||||||
#include <hex/ui/view.hpp>
|
#include <hex/ui/view.hpp>
|
||||||
@ -13,6 +14,7 @@ namespace hex {
|
|||||||
std::atomic<bool> s_paused;
|
std::atomic<bool> s_paused;
|
||||||
std::optional<Shortcut> s_prevShortcut;
|
std::optional<Shortcut> s_prevShortcut;
|
||||||
bool s_macOSMode = false;
|
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());
|
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!");
|
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());
|
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!");
|
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());
|
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!");
|
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());
|
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!");
|
if (!inserted) log::error("Failed to add shortcut!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +287,14 @@ namespace hex {
|
|||||||
|
|
||||||
if (auto it = shortcuts.find(shortcut); it != shortcuts.end()) {
|
if (auto it = shortcuts.find(shortcut); it != shortcuts.end()) {
|
||||||
const auto &[foundShortcut, entry] = *it;
|
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);
|
processShortcut(pressedShortcut, s_globalShortcuts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<UnlocalizedString> ShortcutManager::getLastActivatedMenu() {
|
||||||
|
return *s_lastShortcutMainMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShortcutManager::resetLastActivatedMenu() {
|
||||||
|
s_lastShortcutMainMenu->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ShortcutManager::clearShortcuts() {
|
void ShortcutManager::clearShortcuts() {
|
||||||
s_globalShortcuts->clear();
|
s_globalShortcuts->clear();
|
||||||
}
|
}
|
||||||
|
@ -591,6 +591,8 @@ namespace hex {
|
|||||||
void Window::frame() {
|
void Window::frame() {
|
||||||
auto &io = ImGui::GetIO();
|
auto &io = ImGui::GetIO();
|
||||||
|
|
||||||
|
ShortcutManager::resetLastActivatedMenu();
|
||||||
|
|
||||||
// Loop through all views and draw them
|
// Loop through all views and draw them
|
||||||
for (auto &[name, view] : ContentRegistry::Views::impl::getEntries()) {
|
for (auto &[name, view] : ContentRegistry::Views::impl::getEntries()) {
|
||||||
ImGui::GetCurrentContext()->NextWindowData.ClearFlags();
|
ImGui::GetCurrentContext()->NextWindowData.ClearFlags();
|
||||||
|
@ -503,6 +503,7 @@
|
|||||||
"hex.builtin.setting.interface.native_window_decorations": "Use OS Window decorations",
|
"hex.builtin.setting.interface.native_window_decorations": "Use OS Window decorations",
|
||||||
"hex.builtin.setting.interface.color": "Color theme",
|
"hex.builtin.setting.interface.color": "Color theme",
|
||||||
"hex.builtin.setting.interface.crisp_scaling": "Enable crisp scaling",
|
"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": "FPS Limit",
|
||||||
"hex.builtin.setting.interface.fps.unlocked": "Unlocked",
|
"hex.builtin.setting.interface.fps.unlocked": "Unlocked",
|
||||||
"hex.builtin.setting.interface.fps.native": "Native",
|
"hex.builtin.setting.interface.fps.native": "Native",
|
||||||
|
@ -302,7 +302,8 @@ namespace hex::plugin::builtin {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
std::string fullName;
|
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 += Lang(part).get();
|
||||||
fullName += " -> ";
|
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.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.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.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<std::string> languageNames;
|
||||||
std::vector<nlohmann::json> languageCodes;
|
std::vector<nlohmann::json> languageCodes;
|
||||||
@ -957,14 +959,28 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
/* Shorcuts */
|
/* Shorcuts */
|
||||||
{
|
{
|
||||||
EventImHexStartupFinished::subscribe([]{
|
EventImHexStartupFinished::subscribe([] {
|
||||||
for (const auto &shortcutEntry : ShortcutManager::getGlobalShortcuts()) {
|
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 (auto &[viewName, view] : ContentRegistry::Views::impl::getEntries()) {
|
||||||
for (const auto &shortcutEntry : ShortcutManager::getViewShortcuts(view.get())) {
|
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;
|
u32 s_searchBarPosition = 0;
|
||||||
ImGuiExt::Texture s_logoTexture;
|
ImGuiExt::Texture s_logoTexture;
|
||||||
bool s_showSearchBar = true;
|
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) {
|
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();
|
const auto &name = menuItems.front();
|
||||||
@ -287,7 +288,16 @@ namespace hex::plugin::builtin {
|
|||||||
if (ImGui::BeginMenu(Lang(menuName))) {
|
if (ImGui::BeginMenu(Lang(menuName))) {
|
||||||
populateMenu(menuName);
|
populateMenu(menuName);
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
|
} else {
|
||||||
|
if (s_displayShortcutHighlights) {
|
||||||
|
if (const auto lastShortcutMenu = ShortcutManager::getLastActivatedMenu(); lastShortcutMenu.has_value()) {
|
||||||
|
if (menuName == *lastShortcutMenu) {
|
||||||
|
ImGui::NavHighlightActivated(ImGui::GetItemID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawMenu() {
|
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) {
|
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);
|
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