yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
shortcut_manager.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_SYSTEM_SHORTCUT_MANAGER_H
2#define YAZE_APP_EDITOR_SYSTEM_SHORTCUT_MANAGER_H
3
4#include <functional>
5#include <optional>
6#include <string>
7#include <unordered_map>
8#include <utility>
9#include <vector>
10
11#include "absl/strings/string_view.h"
12
13// Must define before including imgui.h
14#ifndef IMGUI_DEFINE_MATH_OPERATORS
15#define IMGUI_DEFINE_MATH_OPERATORS
16#endif
17
18#include "imgui/imgui.h"
19
20namespace yaze {
21namespace editor {
22
23enum class EditorType;
24
25struct Shortcut {
26 enum class Scope { kGlobal, kEditor, kPanel };
27 std::string name;
29 std::vector<ImGuiKey> keys;
30 std::function<void()> callback;
31 // When set, the shortcut only competes for its chord while this editor is
32 // the active editor (see ShortcutManager::SetActiveEditorProvider).
33 std::optional<EditorType> editor_type;
34 // Optional extra applicability check evaluated before arbitration.
35 std::function<bool()> enabled;
36 // Keys as first registered; ResetShortcutKeys() restores them.
37 std::vector<ImGuiKey> default_keys;
38};
39
40std::vector<ImGuiKey> ParseShortcut(const std::string& shortcut);
41
42std::string PrintShortcut(const std::vector<ImGuiKey>& keys);
43
50std::string InferShortcutGroup(absl::string_view name);
51
53 public:
54 using ActiveEditorProvider = std::function<std::optional<EditorType>()>;
55
56 void RegisterShortcut(const std::string& name,
57 const std::vector<ImGuiKey>& keys,
59 Store({name, scope, keys});
60 }
61 void RegisterShortcut(const std::string& name,
62 const std::vector<ImGuiKey>& keys,
63 std::function<void()> callback,
65 Store({name, scope, keys, std::move(callback)});
66 }
67
68 void RegisterShortcut(const std::string& name, ImGuiKey key,
69 std::function<void()> callback,
71 Store({name, scope, {key}, std::move(callback)});
72 }
73
80 void RegisterEditorShortcut(const std::string& name,
81 const std::vector<ImGuiKey>& keys,
82 std::function<void()> callback,
83 EditorType editor_type) {
84 Shortcut shortcut{name, Shortcut::Scope::kEditor, keys,
85 std::move(callback)};
86 shortcut.editor_type = editor_type;
87 Store(std::move(shortcut));
88 }
89
96 void RegisterCommand(const std::string& name, std::function<void()> callback,
98 Store({name, scope, {}, std::move(callback)}); // Empty key vector
99 }
100
102 bool SetShortcutEditor(const std::string& name,
103 std::optional<EditorType> editor_type);
105 bool SetShortcutEnabled(const std::string& name,
106 std::function<bool()> enabled);
107
111 active_editor_provider_ = std::move(provider);
112 }
113 std::optional<EditorType> GetActiveEditorType() const {
114 return active_editor_provider_ ? active_editor_provider_() : std::nullopt;
115 }
116
118 bool IsShortcutApplicable(const Shortcut& shortcut) const;
119
120 void ExecuteShortcut(const std::string& name) const {
121 shortcuts_.at(name).callback();
122 }
123
124 // Access the shortcut and print the readable name of the shortcut for menus
125 const Shortcut& GetShortcut(const std::string& name) const {
126 return shortcuts_.at(name);
127 }
128
129 const Shortcut* FindShortcut(const std::string& name) const {
130 auto it = shortcuts_.find(name);
131 return it != shortcuts_.end() ? &it->second : nullptr;
132 }
133
134 // Get shortcut callback function
135 std::function<void()> GetCallback(const std::string& name) const {
136 return shortcuts_.at(name).callback;
137 }
138
139 const std::string GetKeys(const std::string& name) const {
140 return PrintShortcut(shortcuts_.at(name).keys);
141 }
142
150 std::string GetDisplayString(const std::string& name) const;
151
152 const std::unordered_map<std::string, Shortcut>& GetShortcuts() const {
153 return shortcuts_;
154 }
155 bool UpdateShortcutKeys(const std::string& name,
156 const std::vector<ImGuiKey>& keys);
158 bool ResetShortcutKeys(const std::string& name);
159
165 std::vector<std::string> FindConflicts(const std::string& name) const;
166 std::vector<std::string> FindConflicts(
167 const std::vector<ImGuiKey>& keys, std::optional<EditorType> editor_type,
168 const std::string& exclude_name = "") const;
169
170 std::vector<Shortcut> GetShortcutsByScope(Shortcut::Scope scope) const {
171 std::vector<Shortcut> result;
172 result.reserve(shortcuts_.size());
173 for (const auto& [_, sc] : shortcuts_) {
174 if (sc.scope == scope)
175 result.push_back(sc);
176 }
177 return result;
178 }
179
180 // Convenience methods for registering common shortcuts
181 void RegisterStandardShortcuts(std::function<void()> save_callback,
182 std::function<void()> open_callback,
183 std::function<void()> close_callback,
184 std::function<void()> find_callback,
185 std::function<void()> settings_callback);
186
187 void RegisterWindowNavigationShortcuts(std::function<void()> focus_left,
188 std::function<void()> focus_right,
189 std::function<void()> focus_up,
190 std::function<void()> focus_down,
191 std::function<void()> close_window,
192 std::function<void()> split_horizontal,
193 std::function<void()> split_vertical);
194
195 private:
196 void Store(Shortcut shortcut) {
197 shortcut.default_keys = shortcut.keys;
198 std::string name = shortcut.name;
199 shortcuts_[name] = std::move(shortcut);
200 }
201
202 std::unordered_map<std::string, Shortcut> shortcuts_;
204};
205
207bool SameChord(const std::vector<ImGuiKey>& a, const std::vector<ImGuiKey>& b);
208
221void ExecuteShortcuts(const ShortcutManager& shortcut_manager);
222
223} // namespace editor
224} // namespace yaze
225
226#endif // YAZE_APP_EDITOR_SYSTEM_SHORTCUT_MANAGER_H
const Shortcut & GetShortcut(const std::string &name) const
const Shortcut * FindShortcut(const std::string &name) const
const std::string GetKeys(const std::string &name) const
void RegisterCommand(const std::string &name, std::function< void()> callback, Shortcut::Scope scope=Shortcut::Scope::kGlobal)
Register a command without keyboard shortcut (command palette only)
std::function< std::optional< EditorType >()> ActiveEditorProvider
bool SetShortcutEditor(const std::string &name, std::optional< EditorType > editor_type)
Restrict an existing shortcut to one editor. Returns false if unknown.
ActiveEditorProvider active_editor_provider_
void RegisterShortcut(const std::string &name, const std::vector< ImGuiKey > &keys, Shortcut::Scope scope=Shortcut::Scope::kGlobal)
bool IsShortcutApplicable(const Shortcut &shortcut) const
True when the shortcut may fire now (editor owner + enabled predicate).
void SetActiveEditorProvider(ActiveEditorProvider provider)
void RegisterShortcut(const std::string &name, ImGuiKey key, std::function< void()> callback, Shortcut::Scope scope=Shortcut::Scope::kGlobal)
void Store(Shortcut shortcut)
std::function< void()> GetCallback(const std::string &name) const
std::vector< Shortcut > GetShortcutsByScope(Shortcut::Scope scope) const
void RegisterShortcut(const std::string &name, const std::vector< ImGuiKey > &keys, std::function< void()> callback, Shortcut::Scope scope=Shortcut::Scope::kGlobal)
void RegisterStandardShortcuts(std::function< void()> save_callback, std::function< void()> open_callback, std::function< void()> close_callback, std::function< void()> find_callback, std::function< void()> settings_callback)
bool SetShortcutEnabled(const std::string &name, std::function< bool()> enabled)
Attach an applicability predicate. Returns false if unknown.
void RegisterWindowNavigationShortcuts(std::function< void()> focus_left, std::function< void()> focus_right, std::function< void()> focus_up, std::function< void()> focus_down, std::function< void()> close_window, std::function< void()> split_horizontal, std::function< void()> split_vertical)
std::string GetDisplayString(const std::string &name) const
Live, platform-formatted binding for a shortcut name.
bool ResetShortcutKeys(const std::string &name)
Restore the keys the shortcut was registered with.
void ExecuteShortcut(const std::string &name) const
std::unordered_map< std::string, Shortcut > shortcuts_
void RegisterEditorShortcut(const std::string &name, const std::vector< ImGuiKey > &keys, std::function< void()> callback, EditorType editor_type)
Register an editor-owned shortcut (Scope::kEditor).
const std::unordered_map< std::string, Shortcut > & GetShortcuts() const
std::vector< std::string > FindConflicts(const std::string &name) const
Names of other shortcuts bound to the same chord that can be active at the same time (same editor own...
std::optional< EditorType > GetActiveEditorType() const
bool UpdateShortcutKeys(const std::string &name, const std::vector< ImGuiKey > &keys)
std::string InferShortcutGroup(absl::string_view name)
Menu-IA group for a shortcut/command name (File, View, Drawers, …).
bool SameChord(const std::vector< ImGuiKey > &a, const std::vector< ImGuiKey > &b)
True when two key lists describe the same chord (order-insensitive).
std::vector< ImGuiKey > ParseShortcut(const std::string &shortcut)
std::string PrintShortcut(const std::vector< ImGuiKey > &keys)
void ExecuteShortcuts(const ShortcutManager &shortcut_manager)
Fire at most one shortcut for this frame's key press.
std::function< void()> callback
std::vector< ImGuiKey > keys
std::function< bool()> enabled
std::vector< ImGuiKey > default_keys
std::optional< EditorType > editor_type