openMSX
Shortcuts.cc
Go to the documentation of this file.
1#include "Shortcuts.hh"
2
3#include "narrow.hh"
4#include "one_of.hh"
5
6#include "imgui_internal.h"
7
8#include <array>
9#include <utility>
10
11namespace openmsx {
12
13// When adding a new shortcut:
14// * Add a new value in 'enum Shortcuts::ID'
15// * Add a single line in this table
18 ImGuiKeyChord keyChord;
20 bool repeat;
21 zstring_view name; // used in settings.xml
22 zstring_view description; // shown in GUI
23};
24using enum Shortcuts::ID;
25using enum Shortcuts::Type;
26static constexpr auto allShortcutInfo = std::to_array<AllShortcutInfo>({
27 {HEX_GOTO_ADDR, ImGuiKey_G | ImGuiMod_Ctrl, ALWAYS_LOCAL, false, "hex_editor_goto_address", "Go to address in hex viewer"},
28 {DEBUGGER_STEP_IN, ImGuiKey_F7, LOCAL, true, "step-in", "Debugger: step-in"},
29 {DEBUGGER_STEP_OVER, ImGuiKey_F8, LOCAL, true, "step-over", "Debugger: step-over"},
30 {DEBUGGER_STEP_OUT, ImGuiKey_F7 | ImGuiMod_Shift, LOCAL, true, "step-out", "Debugger: step-out"},
31 {DEBUGGER_STEP_BACK, ImGuiKey_F8 | ImGuiMod_Shift, LOCAL, true, "step-back", "Debugger: step-back"},
32 {DEBUGGER_BREAK_CONTINUE, ImGuiKey_F5, LOCAL, false, "break-continue", "Debugger: toggle break / continue"},
33 {DISASM_GOTO_ADDR, ImGuiMod_Ctrl | ImGuiKey_G, ALWAYS_LOCAL, false, "disasm_goto_address", "Scroll to address in disassembler"},
34 {DISASM_RUN_TO_ADDR, ImGuiMod_Ctrl | ImGuiKey_R, ALWAYS_LOCAL, false, "disasm_run_to_address", "Debugger: run to a specific address"},
35 {DISASM_TOGGLE_BREAKPOINT,ImGuiMod_Ctrl | ImGuiKey_B, ALWAYS_LOCAL, false, "disasm_toggle_breakpoint","Debugger: toggle breakpoint at current address"},
36});
37static_assert(narrow<int>(allShortcutInfo.size()) == std::to_underlying(Shortcuts::ID::NUM));
38
39static constexpr auto defaultShortcuts = []{
41 for (int i = 0; i < std::to_underlying(Shortcuts::ID::NUM); ++i) {
42 const auto& all = allShortcutInfo[i];
43 auto id = static_cast<Shortcuts::ID>(i);
44 assert(all.id == id); // verify that rows are in-order
45 result[id].keyChord = all.keyChord;
46 result[id].type = all.type;
47 }
48 return result;
49}();
50
51static constexpr auto shortcutRepeats = []{
53 for (int i = 0; i < std::to_underlying(Shortcuts::ID::NUM); ++i) {
54 auto id = static_cast<Shortcuts::ID>(i);
55 result[id] = allShortcutInfo[i].repeat;
56 }
57 return result;
58}();
59
60static constexpr auto shortcutNames = []{
62 for (int i = 0; i < std::to_underlying(Shortcuts::ID::NUM); ++i) {
63 auto id = static_cast<Shortcuts::ID>(i);
64 result[id] = allShortcutInfo[i].name;
65 }
66 return result;
67}();
68
69static constexpr auto shortcutDescriptions = []{
71 for (int i = 0; i < std::to_underlying(Shortcuts::ID::NUM); ++i) {
72 auto id = static_cast<Shortcuts::ID>(i);
73 result[id] = allShortcutInfo[i].description;
74 }
75 return result;
76}();
77
82
84{
85 shortcuts = defaultShortcuts; // this can overwrite the 'type' field
86}
87
89{
90 return defaultShortcuts[id];
91}
92
94{
95 return shortcuts[id];
96}
97
98void Shortcuts::setShortcut(ID id, const Shortcut& shortcut)
99{
100 auto oldType = shortcuts[id].type;
101 shortcuts[id] = shortcut;
103 // cannot change this
104 shortcuts[id].type = oldType;
105 }
106}
107
109{
110 return shortcutRepeats[id];
111}
112
114{
115 return shortcutNames[id];
116}
117
118std::optional<Shortcuts::ID> Shortcuts::parseShortcutName(std::string_view name)
119{
120 auto it = ranges::find(shortcutNames, name);
121 if (it == shortcutNames.end()) return {};
122 return static_cast<Shortcuts::ID>(std::distance(shortcutNames.begin(), it));
123}
124
125std::optional<Shortcuts::Type> Shortcuts::parseType(std::string_view name)
126{
127 if (name == "global") return GLOBAL;
128 if (name == "local") return LOCAL;
129 return {};
130}
131
133{
134 return shortcutDescriptions[id];
135}
136
138{
139 assert(shortcut.keyChord != ImGuiKey_None);
140 auto flags = (shortcut.type == one_of(GLOBAL, ALWAYS_GLOBAL) ? (ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteUnlessBgFocused) : 0)
141 | (shortcut.repeat ? ImGuiInputFlags_Repeat : 0);
142 return ImGui::Shortcut(shortcut.keyChord, flags, 0);
143}
144
146{
147 const auto& shortcut = shortcuts[id];
148 if (shortcut.keyChord == ImGuiKey_None) return false;
149 return checkShortcut({shortcut.keyChord, shortcut.type, getShortcutRepeat(id)});
150}
151
152} // namespace openmsx
uintptr_t id
static zstring_view getShortcutName(ID id)
Definition Shortcuts.cc:113
void setDefaultShortcuts()
Definition Shortcuts.cc:83
static const Shortcut & getDefaultShortcut(ID id)
Definition Shortcuts.cc:88
static zstring_view getShortcutDescription(ID id)
Definition Shortcuts.cc:132
bool checkShortcut(const ShortcutWithRepeat &shortcut) const
Definition Shortcuts.cc:137
static std::optional< ID > parseShortcutName(std::string_view name)
Definition Shortcuts.cc:118
static std::optional< Type > parseType(std::string_view name)
Definition Shortcuts.cc:125
void setShortcut(ID id, const Shortcut &shortcut)
Definition Shortcuts.cc:98
const Shortcut & getShortcut(ID id) const
Definition Shortcuts.cc:93
static bool getShortcutRepeat(ID id)
Definition Shortcuts.cc:108
Like std::string_view, but with the extra guarantee that it refers to a zero-terminated string.
This file implemented 3 utility functions:
Definition Autofire.cc:11
auto find(InputRange &&range, const T &value)
Definition ranges.hh:162
Shortcuts::Type type
Definition Shortcuts.cc:19
zstring_view description
Definition Shortcuts.cc:22
ImGuiKeyChord keyChord
Definition Shortcuts.cc:18