14#include "imgui/imgui.h"
27 {ImGuiKey_Tab,
"Tab"},
28 {ImGuiKey_LeftArrow,
"Left"},
29 {ImGuiKey_RightArrow,
"Right"},
30 {ImGuiKey_UpArrow,
"Up"},
31 {ImGuiKey_DownArrow,
"Down"},
32 {ImGuiKey_PageUp,
"PageUp"},
33 {ImGuiKey_PageDown,
"PageDown"},
34 {ImGuiKey_Home,
"Home"},
35 {ImGuiKey_End,
"End"},
36 {ImGuiKey_Insert,
"Insert"},
37 {ImGuiKey_Delete,
"Delete"},
38 {ImGuiKey_Backspace,
"Backspace"},
39 {ImGuiKey_Space,
"Space"},
40 {ImGuiKey_Enter,
"Enter"},
41 {ImGuiKey_Escape,
"Escape"},
87 {ImGuiKey_F10,
"F10"},
88 {ImGuiKey_F11,
"F11"},
89 {ImGuiKey_F12,
"F12"},
90 {ImGuiKey_Minus,
"-"},
91 {ImGuiKey_Equal,
"="},
92 {ImGuiKey_LeftBracket,
"["},
93 {ImGuiKey_RightBracket,
"]"},
94 {ImGuiKey_Backslash,
"\\"},
95 {ImGuiKey_Semicolon,
";"},
96 {ImGuiKey_Apostrophe,
"'"},
97 {ImGuiKey_Comma,
","},
98 {ImGuiKey_Period,
"."},
99 {ImGuiKey_Slash,
"/"},
100 {ImGuiKey_GraveAccent,
"`"},
105 if (entry.key ==
key) {
140 if (pressed_key !=
key)
161 const std::string& description,
162 ImGuiKey key,
bool ctrl,
bool shift,
163 bool alt,
const std::string& category,
165 std::function<
void()> action) {
188 it->second.enabled = enabled;
195 return ImGui::GetIO().WantTextInput;
205 const auto& io = ImGui::GetIO();
206 bool ctrl = io.KeyCtrl;
207 bool shift = io.KeyShift;
208 bool alt = io.KeyAlt;
212 if (ImGui::IsKeyPressed(ImGuiKey_Slash) && shift && !ctrl && !alt) {
217 }
else if (!ImGui::IsKeyPressed(ImGuiKey_Slash)) {
233 for (
const auto& [
id, shortcut] :
shortcuts_) {
234 if (!shortcut.enabled)
240 if (ImGui::IsKeyPressed(shortcut.key,
false)) {
241 if (shortcut.Matches(shortcut.key, ctrl, shift, alt)) {
242 if (shortcut.action) {
263 ImGuiIO& io = ImGui::GetIO();
264 ImGui::SetNextWindowPos(ImVec2(0, 0));
265 ImGui::SetNextWindowSize(io.DisplaySize);
266 ImGuiWindowFlags overlay_flags =
267 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
268 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar |
269 ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoBringToFrontOnFocus;
273 {.bg = ImVec4(0.0f, 0.0f, 0.0f, 0.7f),
274 .padding = ImVec2(0, 0),
275 .border_size = 0.0f},
276 nullptr, overlay_flags);
279 if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(0)) {
280 ImVec2 mouse = ImGui::GetMousePos();
281 ImVec2 modal_pos = ImVec2((io.DisplaySize.x - 600) * 0.5f,
282 (io.DisplaySize.y - 500) * 0.5f);
283 ImVec2 modal_size = ImVec2(600, 500);
285 if (mouse.x < modal_pos.x || mouse.x > modal_pos.x + modal_size.x ||
286 mouse.y < modal_pos.y || mouse.y > modal_pos.y + modal_size.y) {
299 ImGuiIO& io = ImGui::GetIO();
302 float modal_width = 600.0f;
303 float modal_height = 500.0f;
304 ImVec2 modal_pos((io.DisplaySize.x - modal_width) * 0.5f,
305 (io.DisplaySize.y - modal_height) * 0.5f);
307 ImGui::SetNextWindowPos(modal_pos);
308 ImGui::SetNextWindowSize(ImVec2(modal_width, modal_height));
311 ImGuiWindowFlags modal_flags =
312 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
313 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse |
314 ImGuiWindowFlags_NoSavedSettings;
319 .padding = ImVec2(20, 16),
322 nullptr, modal_flags);
326 ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]);
328 tr(
"Keyboard Shortcuts"));
331 ImGui::SameLine(modal_width - 60);
332 if (ImGui::SmallButton(tr(
"X##CloseOverlay"))) {
335 if (ImGui::IsItemHovered()) {
336 ImGui::SetTooltip(tr(
"Close (Escape)"));
343 ImGui::SetNextItemWidth(modal_width - 40);
345 StyleVarGuard frame_rounding(ImGuiStyleVar_FrameRounding, 4.0f);
346 ImGui::InputTextWithHint(
"##ShortcutSearch",
"Search shortcuts...",
359 ImGui::BeginChild(
"##ShortcutList", ImVec2(0, -30),
false,
360 ImGuiWindowFlags_AlwaysVerticalScrollbar);
363 std::map<std::string, std::vector<const Shortcut*>> shortcuts_by_category;
364 std::string filter_lower;
366 filter_lower +=
static_cast<char>(std::tolower(c));
369 for (
const auto& [
id, shortcut] :
shortcuts_) {
371 if (!filter_lower.empty()) {
372 std::string desc_lower;
373 for (
char c : shortcut.description) {
374 desc_lower +=
static_cast<char>(std::tolower(c));
376 std::string cat_lower;
377 for (
char c : shortcut.category) {
378 cat_lower +=
static_cast<char>(std::tolower(c));
380 std::string key_lower;
381 for (
char c : shortcut.GetDisplayString()) {
382 key_lower +=
static_cast<char>(std::tolower(c));
385 if (desc_lower.find(filter_lower) == std::string::npos &&
386 cat_lower.find(filter_lower) == std::string::npos &&
387 key_lower.find(filter_lower) == std::string::npos) {
392 shortcuts_by_category[shortcut.category].push_back(&shortcut);
397 auto it = shortcuts_by_category.find(category);
398 if (it != shortcuts_by_category.end() && !it->second.empty()) {
404 for (
const auto& [category, shortcuts] : shortcuts_by_category) {
405 bool in_order =
false;
407 if (ordered == category) {
412 if (!in_order && !shortcuts.empty()) {
421 ImGui::TextDisabled(tr(
"Press ? to toggle | Escape to close"));
426 const std::string& category,
427 const std::vector<const Shortcut*>& shortcuts) {
433 {ImGuiCol_Header, header_bg},
434 {ImGuiCol_HeaderHovered, ImVec4(header_bg.x + 0.05f, header_bg.y + 0.05f,
435 header_bg.z + 0.05f, 1.0f)},
439 ImGui::CollapsingHeader(category.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
442 ImGui::Indent(10.0f);
445 if (ImGui::BeginTable(
446 "##ShortcutTable", 3,
447 ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_RowBg)) {
448 ImGui::TableSetupColumn(
"Shortcut", ImGuiTableColumnFlags_WidthFixed,
450 ImGui::TableSetupColumn(
"Description",
451 ImGuiTableColumnFlags_WidthStretch);
452 ImGui::TableSetupColumn(
"Context", ImGuiTableColumnFlags_WidthFixed,
455 for (
const auto* shortcut : shortcuts) {
462 ImGui::Unindent(10.0f);
470 ImGui::TableNextRow();
473 ImGui::TableNextColumn();
478 {ImGuiCol_Button, is_active ? ImVec4(0.2f, 0.3f, 0.4f, 0.8f)
479 : ImVec4(0.15f, 0.15f, 0.15f, 0.6f)},
480 {ImGuiCol_ButtonHovered, is_active ? ImVec4(0.25f, 0.35f, 0.45f, 0.9f)
481 : ImVec4(0.2f, 0.2f, 0.2f, 0.7f)},
484 {ImGuiStyleVar_FrameRounding, 4.0f},
485 {ImGuiStyleVar_FramePadding, ImVec2(6, 2)},
489 ImGui::SmallButton(display.c_str());
492 ImGui::TableNextColumn();
495 ImGui::TextColored(text_color,
"%s", shortcut.
description.c_str());
498 ImGui::TableNextColumn();
513 const std::string& category)
const {
514 std::vector<const Shortcut*> result;
515 for (
const auto& [
id, shortcut] :
shortcuts_) {
516 if (shortcut.category == category) {
517 result.push_back(&shortcut);
524 std::vector<const Shortcut*> result;
525 for (
const auto& [
id, shortcut] :
shortcuts_) {
527 result.push_back(&shortcut);
534 std::vector<std::string> result;
535 for (
const auto& [
id, shortcut] :
shortcuts_) {
537 for (
const auto& cat : result) {
538 if (cat == shortcut.category) {
544 result.push_back(shortcut.category);
551 std::function<
void()> open_callback, std::function<
void()> save_callback,
552 std::function<
void()> save_as_callback,
553 std::function<
void()> close_callback, std::function<
void()> undo_callback,
554 std::function<
void()> redo_callback, std::function<
void()> copy_callback,
555 std::function<
void()> paste_callback, std::function<
void()> cut_callback,
556 std::function<
void()> find_callback) {
569 if (save_as_callback) {
574 if (close_callback) {
599 if (paste_callback) {
615 RegisterShortcut(
"view.fullscreen",
"Toggle Fullscreen", ImGuiKey_F11,
false,
619 RegisterShortcut(
"view.grid",
"Toggle Grid", ImGuiKey_G,
true,
false,
false,
640 RegisterShortcut(
"nav.last",
"Go to Last", ImGuiKey_End,
false,
false,
false,
644 RegisterShortcut(
"nav.prev",
"Previous", ImGuiKey_PageUp,
false,
false,
false,
648 RegisterShortcut(
"nav.next",
"Next", ImGuiKey_PageDown,
false,
false,
false,
666 RegisterShortcut(
"ow.select_all",
"Select All Tiles", ImGuiKey_A,
true,
false,
716 if (editor_name ==
"Overworld")
718 if (editor_name ==
"Dungeon")
720 if (editor_name ==
"Graphics")
722 if (editor_name ==
"Palette")
724 if (editor_name ==
"Sprite")
726 if (editor_name ==
"Music")
728 if (editor_name ==
"Message")
730 if (editor_name ==
"Emulator")
732 if (editor_name ==
"Assembly" || editor_name ==
"Code")
Manages keyboard shortcuts and provides an overlay UI.
void SetShortcutEnabled(const std::string &id, bool enabled)
void UnregisterShortcut(const std::string &id)
std::vector< std::string > category_order_
std::vector< std::string > GetCategories() const
std::map< std::string, Shortcut > shortcuts_
void DrawShortcutRow(const Shortcut &shortcut)
bool toggle_key_was_pressed_
std::vector< const Shortcut * > GetContextShortcuts() const
static bool IsTextInputActive()
void DrawOverlayContent()
std::vector< const Shortcut * > GetShortcutsInCategory(const std::string &category) const
static KeyboardShortcuts & Get()
void DrawCategorySection(const std::string &category, const std::vector< const Shortcut * > &shortcuts)
void RegisterShortcut(const Shortcut &shortcut)
ShortcutContext current_context_
void RegisterDefaultShortcuts(std::function< void()> open_callback, std::function< void()> save_callback, std::function< void()> save_as_callback, std::function< void()> close_callback, std::function< void()> undo_callback, std::function< void()> redo_callback, std::function< void()> copy_callback, std::function< void()> paste_callback, std::function< void()> cut_callback, std::function< void()> find_callback)
bool IsShortcutActiveInContext(const Shortcut &shortcut) const
RAII guard for ImGui style colors.
RAII guard for ImGui style vars.
RAII compound guard for window-level style setup.
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
const char * GetLocalKeyName(ImGuiKey key)
constexpr struct yaze::gui::anonymous_namespace{keyboard_shortcuts.cc}::@1 kLocalKeyNames[]
const char * GetCtrlDisplayName()
Get the display name for the primary modifier key.
ImVec4 ConvertColorToImVec4(const Color &color)
const char * ShortcutContextToString(ShortcutContext context)
Convert ShortcutContext to display string.
ShortcutContext EditorNameToContext(const std::string &editor_name)
Convert editor type name to ShortcutContext.
const char * GetKeyName(ImGuiKey key)
Get the ImGui key name as a string.
ShortcutContext
Defines the context in which a shortcut is active.
const char * GetAltDisplayName()
Get the display name for the secondary modifier key.
Represents a keyboard shortcut with its associated action.
std::string GetDisplayString() const
std::function< void()> action
bool Matches(ImGuiKey pressed_key, bool ctrl, bool shift, bool alt) const