mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-02 21:47:40 -05:00
feat: Add shortcut editor to settings
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
@@ -132,13 +133,14 @@ namespace hex {
|
||||
|
||||
class Key {
|
||||
public:
|
||||
constexpr Key() = default;
|
||||
constexpr Key(Keys key) : m_key(static_cast<u32>(key)) { }
|
||||
|
||||
auto operator<=>(const Key &) const = default;
|
||||
|
||||
[[nodiscard]] constexpr u32 getKeyCode() const { return this->m_key; }
|
||||
private:
|
||||
u32 m_key;
|
||||
u32 m_key = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -159,6 +161,13 @@ namespace hex {
|
||||
public:
|
||||
Shortcut() = default;
|
||||
Shortcut(Keys key) : m_keys({ key }) { }
|
||||
explicit Shortcut(std::set<Key> keys) : m_keys(std::move(keys)) { }
|
||||
Shortcut(const Shortcut &other) = default;
|
||||
Shortcut(Shortcut &&) noexcept = default;
|
||||
|
||||
Shortcut& operator=(const Shortcut &other) = default;
|
||||
|
||||
Shortcut& operator=(Shortcut &&) noexcept = default;
|
||||
|
||||
constexpr static inline auto None = Keys(0);
|
||||
|
||||
@@ -350,6 +359,8 @@ namespace hex {
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::set<Key>& getKeys() const { return this->m_keys; }
|
||||
|
||||
private:
|
||||
friend Shortcut operator+(const Key &lhs, const Key &rhs);
|
||||
|
||||
@@ -369,21 +380,29 @@ namespace hex {
|
||||
*/
|
||||
class ShortcutManager {
|
||||
public:
|
||||
using Callback = std::function<void()>;
|
||||
struct ShortcutEntry {
|
||||
Shortcut shortcut;
|
||||
std::string unlocalizedName;
|
||||
Callback callback;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Add a global shortcut. Global shortcuts can be triggered regardless of what view is currently focused
|
||||
* @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.
|
||||
*/
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const std::function<void()> &callback);
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const std::string &unlocalizedName, const Callback &callback);
|
||||
|
||||
/**
|
||||
* @brief Add a view-specific shortcut. View-specific shortcuts can only be triggered when the specified view is focused.
|
||||
* @param view The view to add the shortcut to.
|
||||
* @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.
|
||||
*/
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const std::function<void()> &callback);
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const std::string &unlocalizedName, const Callback &callback);
|
||||
|
||||
|
||||
/**
|
||||
@@ -412,6 +431,16 @@ namespace hex {
|
||||
* @brief Clear all shortcuts
|
||||
*/
|
||||
static void clearShortcuts();
|
||||
|
||||
static void resumeShortcuts();
|
||||
static void pauseShortcuts();
|
||||
|
||||
static std::optional<Shortcut> getPreviousShortcut();
|
||||
|
||||
static std::vector<ShortcutEntry> getGlobalShortcuts();
|
||||
static std::vector<ShortcutEntry> getViewShortcuts(View *view);
|
||||
|
||||
static void updateShortcut(const Shortcut &oldShortcut, const Shortcut &newShortcut, View *view = nullptr);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -50,7 +50,7 @@ namespace hex {
|
||||
static void confirmButtons(const std::string &textLeft, const std::string &textRight, const std::function<void()> &leftButtonFn, const std::function<void()> &rightButtonFn);
|
||||
static void discardNavigationRequests();
|
||||
|
||||
static inline std::string toWindowName(const std::string &unlocalizedName) {
|
||||
static std::string toWindowName(const std::string &unlocalizedName) {
|
||||
return LangEntry(unlocalizedName) + "###" + unlocalizedName;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace hex {
|
||||
private:
|
||||
std::string m_unlocalizedViewName;
|
||||
bool m_windowOpen = false;
|
||||
std::map<Shortcut, std::function<void()>> m_shortcuts;
|
||||
std::map<Shortcut, ShortcutManager::ShortcutEntry> m_shortcuts;
|
||||
bool m_windowJustOpened = false;
|
||||
|
||||
friend class ShortcutManager;
|
||||
|
||||
@@ -714,10 +714,12 @@ namespace hex {
|
||||
priority, { unlocalizedMainMenuNames, shortcut, function, enabledCallback }
|
||||
});
|
||||
|
||||
if (shortcut.isLocal() && view != nullptr)
|
||||
ShortcutManager::addShortcut(view, shortcut, function);
|
||||
else
|
||||
ShortcutManager::addGlobalShortcut(shortcut, function);
|
||||
if (shortcut != Shortcut::None) {
|
||||
if (shortcut.isLocal() && view != nullptr)
|
||||
ShortcutManager::addShortcut(view, shortcut, unlocalizedMainMenuNames.back(), function);
|
||||
else
|
||||
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedMainMenuNames.back(), function);
|
||||
}
|
||||
}
|
||||
|
||||
void addMenuItemSubMenu(std::vector<std::string> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <hex/api/keybinding.hpp>
|
||||
#include <imgui.h>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <hex/ui/view.hpp>
|
||||
|
||||
@@ -7,17 +8,19 @@ namespace hex {
|
||||
|
||||
namespace {
|
||||
|
||||
std::map<Shortcut, std::function<void()>> s_globalShortcuts;
|
||||
std::map<Shortcut, ShortcutManager::ShortcutEntry> s_globalShortcuts;
|
||||
std::atomic<bool> s_paused;
|
||||
std::optional<Shortcut> s_prevShortcut;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::function<void()> &callback) {
|
||||
s_globalShortcuts.insert({ shortcut, callback });
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::string &unlocalizedName, const std::function<void()> &callback) {
|
||||
s_globalShortcuts.insert({ shortcut, { shortcut, unlocalizedName, callback } });
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::function<void()> &callback) {
|
||||
view->m_shortcuts.insert({ shortcut + CurrentView, callback });
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::string &unlocalizedName, const std::function<void()> &callback) {
|
||||
view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback } });
|
||||
}
|
||||
|
||||
static Shortcut getShortcut(bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode) {
|
||||
@@ -42,22 +45,38 @@ namespace hex {
|
||||
void ShortcutManager::process(const std::unique_ptr<View> ¤tView, bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode) {
|
||||
Shortcut pressedShortcut = getShortcut(ctrl, alt, shift, super, focused, keyCode);
|
||||
|
||||
if (keyCode != 0)
|
||||
s_prevShortcut = Shortcut(pressedShortcut.getKeys());
|
||||
|
||||
if (s_paused) return;
|
||||
|
||||
if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId))
|
||||
return;
|
||||
|
||||
if (currentView->m_shortcuts.contains(pressedShortcut + AllowWhileTyping)) {
|
||||
currentView->m_shortcuts[pressedShortcut + AllowWhileTyping]();
|
||||
currentView->m_shortcuts[pressedShortcut + AllowWhileTyping].callback();
|
||||
} else if (currentView->m_shortcuts.contains(pressedShortcut)) {
|
||||
if (!ImGui::GetIO().WantTextInput)
|
||||
currentView->m_shortcuts[pressedShortcut]();
|
||||
currentView->m_shortcuts[pressedShortcut].callback();
|
||||
}
|
||||
}
|
||||
|
||||
void ShortcutManager::processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode) {
|
||||
Shortcut pressedShortcut = getShortcut(ctrl, alt, shift, super, false, keyCode);
|
||||
|
||||
if (keyCode != 0)
|
||||
s_prevShortcut = pressedShortcut;
|
||||
|
||||
if (s_paused) return;
|
||||
|
||||
if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId))
|
||||
return;
|
||||
|
||||
if (s_globalShortcuts.contains(pressedShortcut + AllowWhileTyping)) {
|
||||
s_globalShortcuts[pressedShortcut + AllowWhileTyping]();
|
||||
s_globalShortcuts[pressedShortcut + AllowWhileTyping].callback();
|
||||
} else if (s_globalShortcuts.contains(pressedShortcut)) {
|
||||
if (!ImGui::GetIO().WantTextInput)
|
||||
s_globalShortcuts[pressedShortcut]();
|
||||
s_globalShortcuts[pressedShortcut].callback();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,4 +84,54 @@ namespace hex {
|
||||
s_globalShortcuts.clear();
|
||||
}
|
||||
|
||||
void ShortcutManager::resumeShortcuts() {
|
||||
s_paused = false;
|
||||
}
|
||||
|
||||
void ShortcutManager::pauseShortcuts() {
|
||||
s_paused = true;
|
||||
s_prevShortcut.reset();
|
||||
}
|
||||
|
||||
std::optional<Shortcut> ShortcutManager::getPreviousShortcut() {
|
||||
return s_prevShortcut;
|
||||
}
|
||||
|
||||
std::vector<ShortcutManager::ShortcutEntry> ShortcutManager::getGlobalShortcuts() {
|
||||
std::vector<ShortcutManager::ShortcutEntry> result;
|
||||
|
||||
for (auto &[shortcut, entry] : s_globalShortcuts)
|
||||
result.push_back(entry);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<ShortcutManager::ShortcutEntry> ShortcutManager::getViewShortcuts(View *view) {
|
||||
std::vector<ShortcutManager::ShortcutEntry> result;
|
||||
|
||||
for (auto &[shortcut, entry] : view->m_shortcuts)
|
||||
result.push_back(entry);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ShortcutManager::updateShortcut(const Shortcut &oldShortcut, const Shortcut &newShortcut, View *view) {
|
||||
if (oldShortcut == newShortcut)
|
||||
return;
|
||||
|
||||
if (view != nullptr) {
|
||||
if (view->m_shortcuts.contains(oldShortcut + CurrentView)) {
|
||||
view->m_shortcuts[newShortcut + CurrentView] = view->m_shortcuts[oldShortcut + CurrentView];
|
||||
view->m_shortcuts[newShortcut + CurrentView].shortcut = newShortcut + CurrentView;
|
||||
view->m_shortcuts.erase(oldShortcut + CurrentView);
|
||||
}
|
||||
} else {
|
||||
if (s_globalShortcuts.contains(oldShortcut)) {
|
||||
s_globalShortcuts[newShortcut] = s_globalShortcuts[oldShortcut];
|
||||
s_globalShortcuts[newShortcut].shortcut = newShortcut;
|
||||
s_globalShortcuts.erase(oldShortcut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user