yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
keyboard_shortcuts.cc
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2// Implementation of keyboard shortcut overlay system for yaze
3
5
6#include <algorithm>
7#include <cstring>
8
13#include "imgui/imgui.h"
14
15namespace yaze {
16namespace gui {
17
18namespace {
19
20// Key name lookup table (local to this file for Shortcut::GetDisplayString)
21// Note: gui::GetKeyName from platform_keys.h is the canonical version
22constexpr struct {
23 ImGuiKey key;
24 const char* name;
25} kLocalKeyNames[] = {
26 {ImGuiKey_Tab, "Tab"},
27 {ImGuiKey_LeftArrow, "Left"},
28 {ImGuiKey_RightArrow, "Right"},
29 {ImGuiKey_UpArrow, "Up"},
30 {ImGuiKey_DownArrow, "Down"},
31 {ImGuiKey_PageUp, "PageUp"},
32 {ImGuiKey_PageDown, "PageDown"},
33 {ImGuiKey_Home, "Home"},
34 {ImGuiKey_End, "End"},
35 {ImGuiKey_Insert, "Insert"},
36 {ImGuiKey_Delete, "Delete"},
37 {ImGuiKey_Backspace, "Backspace"},
38 {ImGuiKey_Space, "Space"},
39 {ImGuiKey_Enter, "Enter"},
40 {ImGuiKey_Escape, "Escape"},
41 {ImGuiKey_A, "A"},
42 {ImGuiKey_B, "B"},
43 {ImGuiKey_C, "C"},
44 {ImGuiKey_D, "D"},
45 {ImGuiKey_E, "E"},
46 {ImGuiKey_F, "F"},
47 {ImGuiKey_G, "G"},
48 {ImGuiKey_H, "H"},
49 {ImGuiKey_I, "I"},
50 {ImGuiKey_J, "J"},
51 {ImGuiKey_K, "K"},
52 {ImGuiKey_L, "L"},
53 {ImGuiKey_M, "M"},
54 {ImGuiKey_N, "N"},
55 {ImGuiKey_O, "O"},
56 {ImGuiKey_P, "P"},
57 {ImGuiKey_Q, "Q"},
58 {ImGuiKey_R, "R"},
59 {ImGuiKey_S, "S"},
60 {ImGuiKey_T, "T"},
61 {ImGuiKey_U, "U"},
62 {ImGuiKey_V, "V"},
63 {ImGuiKey_W, "W"},
64 {ImGuiKey_X, "X"},
65 {ImGuiKey_Y, "Y"},
66 {ImGuiKey_Z, "Z"},
67 {ImGuiKey_0, "0"},
68 {ImGuiKey_1, "1"},
69 {ImGuiKey_2, "2"},
70 {ImGuiKey_3, "3"},
71 {ImGuiKey_4, "4"},
72 {ImGuiKey_5, "5"},
73 {ImGuiKey_6, "6"},
74 {ImGuiKey_7, "7"},
75 {ImGuiKey_8, "8"},
76 {ImGuiKey_9, "9"},
77 {ImGuiKey_F1, "F1"},
78 {ImGuiKey_F2, "F2"},
79 {ImGuiKey_F3, "F3"},
80 {ImGuiKey_F4, "F4"},
81 {ImGuiKey_F5, "F5"},
82 {ImGuiKey_F6, "F6"},
83 {ImGuiKey_F7, "F7"},
84 {ImGuiKey_F8, "F8"},
85 {ImGuiKey_F9, "F9"},
86 {ImGuiKey_F10, "F10"},
87 {ImGuiKey_F11, "F11"},
88 {ImGuiKey_F12, "F12"},
89 {ImGuiKey_Minus, "-"},
90 {ImGuiKey_Equal, "="},
91 {ImGuiKey_LeftBracket, "["},
92 {ImGuiKey_RightBracket, "]"},
93 {ImGuiKey_Backslash, "\\"},
94 {ImGuiKey_Semicolon, ";"},
95 {ImGuiKey_Apostrophe, "'"},
96 {ImGuiKey_Comma, ","},
97 {ImGuiKey_Period, "."},
98 {ImGuiKey_Slash, "/"},
99 {ImGuiKey_GraveAccent, "`"},
101
102const char* GetLocalKeyName(ImGuiKey key) {
103 for (const auto& entry : kLocalKeyNames) {
104 if (entry.key == key) {
105 return entry.name;
106 }
107 }
108 return "?";
109}
110
111} // namespace
112
113std::string Shortcut::GetDisplayString() const {
114 std::string result;
115
116 // Use runtime platform detection for correct modifier names
117 // This handles native macOS, WASM on Mac browsers, and Windows/Linux
118 if (requires_ctrl) {
119 result += GetCtrlDisplayName();
120 result += "+";
121 }
122 if (requires_alt) {
123 result += GetAltDisplayName();
124 result += "+";
125 }
126 if (requires_shift) {
127 result += "Shift+";
128 }
129
130 // Use platform_keys.h GetKeyName for consistent key name formatting
131 result += gui::GetKeyName(key);
132 return result;
133}
134
135bool Shortcut::Matches(ImGuiKey pressed_key, bool ctrl, bool shift,
136 bool alt) const {
137 if (!enabled) return false;
138 if (pressed_key != key) return false;
139 if (ctrl != requires_ctrl) return false;
140 if (shift != requires_shift) return false;
141 if (alt != requires_alt) return false;
142 return true;
143}
144
146 static KeyboardShortcuts instance;
147 return instance;
148}
149
151 shortcuts_[shortcut.id] = shortcut;
152}
153
154void KeyboardShortcuts::RegisterShortcut(const std::string& id,
155 const std::string& description,
156 ImGuiKey key, bool ctrl, bool shift,
157 bool alt, const std::string& category,
158 ShortcutContext context,
159 std::function<void()> action) {
160 Shortcut shortcut;
161 shortcut.id = id;
162 shortcut.description = description;
163 shortcut.key = key;
164 shortcut.requires_ctrl = ctrl;
165 shortcut.requires_shift = shift;
166 shortcut.requires_alt = alt;
167 shortcut.category = category;
168 shortcut.context = context;
169 shortcut.action = action;
170 shortcut.enabled = true;
171 RegisterShortcut(shortcut);
172}
173
174void KeyboardShortcuts::UnregisterShortcut(const std::string& id) {
175 shortcuts_.erase(id);
176}
177
178void KeyboardShortcuts::SetShortcutEnabled(const std::string& id,
179 bool enabled) {
180 auto it = shortcuts_.find(id);
181 if (it != shortcuts_.end()) {
182 it->second.enabled = enabled;
183 }
184}
185
187 // Check if any ImGui input widget is active (text fields, etc.)
188 // This prevents shortcuts from triggering while the user is typing
189 return ImGui::GetIO().WantTextInput;
190}
191
193 // Don't process shortcuts when text input is active
194 if (IsTextInputActive()) {
196 return;
197 }
198
199 const auto& io = ImGui::GetIO();
200 bool ctrl = io.KeyCtrl;
201 bool shift = io.KeyShift;
202 bool alt = io.KeyAlt;
203
204 // Handle '?' key to toggle overlay (Shift + /)
205 // Note: '?' is typically Shift+Slash on US keyboards
206 if (ImGui::IsKeyPressed(ImGuiKey_Slash) && shift && !ctrl && !alt) {
210 }
211 } else if (!ImGui::IsKeyPressed(ImGuiKey_Slash)) {
213 }
214
215 // Close overlay with Escape
216 if (show_overlay_ && ImGui::IsKeyPressed(ImGuiKey_Escape)) {
217 HideOverlay();
218 return;
219 }
220
221 // Don't process other shortcuts while overlay is shown
222 if (show_overlay_) {
223 return;
224 }
225
226 // Check all registered shortcuts
227 for (const auto& [id, shortcut] : shortcuts_) {
228 if (!shortcut.enabled) continue;
229 if (!IsShortcutActiveInContext(shortcut)) continue;
230
231 // Check if this shortcut's key is pressed
232 if (ImGui::IsKeyPressed(shortcut.key, false)) {
233 if (shortcut.Matches(shortcut.key, ctrl, shift, alt)) {
234 if (shortcut.action) {
235 shortcut.action();
236 }
237 }
238 }
239 }
240}
241
244 if (show_overlay_) {
245 // Clear search filter when opening
246 search_filter_[0] = '\0';
247 }
248}
249
251 if (!show_overlay_) return;
252
253 // Semi-transparent fullscreen background
254 ImGuiIO& io = ImGui::GetIO();
255 ImGui::SetNextWindowPos(ImVec2(0, 0));
256 ImGui::SetNextWindowSize(io.DisplaySize);
257 ImGuiWindowFlags overlay_flags = ImGuiWindowFlags_NoTitleBar |
258 ImGuiWindowFlags_NoResize |
259 ImGuiWindowFlags_NoMove |
260 ImGuiWindowFlags_NoScrollbar |
261 ImGuiWindowFlags_NoSavedSettings |
262 ImGuiWindowFlags_NoBringToFrontOnFocus;
263
264 {
265 StyledWindow overlay_bg(
266 "##ShortcutOverlayBg",
267 {.bg = ImVec4(0.0f, 0.0f, 0.0f, 0.7f),
268 .padding = ImVec2(0, 0),
269 .border_size = 0.0f},
270 nullptr, overlay_flags);
271 if (overlay_bg) {
272 // Close on click outside modal
273 if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(0)) {
274 ImVec2 mouse = ImGui::GetMousePos();
275 ImVec2 modal_pos = ImVec2((io.DisplaySize.x - 600) * 0.5f,
276 (io.DisplaySize.y - 500) * 0.5f);
277 ImVec2 modal_size = ImVec2(600, 500);
278
279 if (mouse.x < modal_pos.x || mouse.x > modal_pos.x + modal_size.x ||
280 mouse.y < modal_pos.y || mouse.y > modal_pos.y + modal_size.y) {
281 HideOverlay();
282 }
283 }
284 }
285 }
286
287 // Draw the centered modal window
289}
290
292 const auto& theme = ThemeManager::Get().GetCurrentTheme();
293 ImGuiIO& io = ImGui::GetIO();
294
295 // Calculate centered position
296 float modal_width = 600.0f;
297 float modal_height = 500.0f;
298 ImVec2 modal_pos((io.DisplaySize.x - modal_width) * 0.5f,
299 (io.DisplaySize.y - modal_height) * 0.5f);
300
301 ImGui::SetNextWindowPos(modal_pos);
302 ImGui::SetNextWindowSize(ImVec2(modal_width, modal_height));
303
304 // Style the modal window
305 ImGuiWindowFlags modal_flags = ImGuiWindowFlags_NoTitleBar |
306 ImGuiWindowFlags_NoResize |
307 ImGuiWindowFlags_NoMove |
308 ImGuiWindowFlags_NoCollapse |
309 ImGuiWindowFlags_NoSavedSettings;
310
311 StyledWindow modal(
312 "##ShortcutOverlay",
313 {.bg = ConvertColorToImVec4(theme.popup_bg),
314 .border = ConvertColorToImVec4(theme.border),
315 .padding = ImVec2(20, 16),
316 .border_size = 1.0f,
317 .rounding = 8.0f},
318 nullptr, modal_flags);
319
320 if (modal) {
321 // Header
322 ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]); // Use default font
323 ImGui::TextColored(ConvertColorToImVec4(theme.accent), "Keyboard Shortcuts");
324 ImGui::PopFont();
325
326 ImGui::SameLine(modal_width - 60);
327 if (ImGui::SmallButton("X##CloseOverlay")) {
328 HideOverlay();
329 }
330 if (ImGui::IsItemHovered()) {
331 ImGui::SetTooltip("Close (Escape)");
332 }
333
334 ImGui::Separator();
335 ImGui::Spacing();
336
337 // Search filter
338 ImGui::SetNextItemWidth(modal_width - 40);
339 {
340 StyleVarGuard frame_rounding(ImGuiStyleVar_FrameRounding, 4.0f);
341 ImGui::InputTextWithHint("##ShortcutSearch", "Search shortcuts...",
343 }
344
345 // Context indicator
346 ImGui::SameLine();
347 ImGui::TextDisabled("(%s)", ShortcutContextToString(current_context_));
348
349 ImGui::Spacing();
350 ImGui::Separator();
351 ImGui::Spacing();
352
353 // Scrollable content area
354 ImGui::BeginChild("##ShortcutList", ImVec2(0, -30), false,
355 ImGuiWindowFlags_AlwaysVerticalScrollbar);
356
357 // Collect shortcuts by category
358 std::map<std::string, std::vector<const Shortcut*>> shortcuts_by_category;
359 std::string filter_lower;
360 for (char c : std::string(search_filter_)) {
361 filter_lower += static_cast<char>(std::tolower(c));
362 }
363
364 for (const auto& [id, shortcut] : shortcuts_) {
365 // Apply search filter
366 if (!filter_lower.empty()) {
367 std::string desc_lower;
368 for (char c : shortcut.description) {
369 desc_lower += static_cast<char>(std::tolower(c));
370 }
371 std::string cat_lower;
372 for (char c : shortcut.category) {
373 cat_lower += static_cast<char>(std::tolower(c));
374 }
375 std::string key_lower;
376 for (char c : shortcut.GetDisplayString()) {
377 key_lower += static_cast<char>(std::tolower(c));
378 }
379
380 if (desc_lower.find(filter_lower) == std::string::npos &&
381 cat_lower.find(filter_lower) == std::string::npos &&
382 key_lower.find(filter_lower) == std::string::npos) {
383 continue;
384 }
385 }
386
387 shortcuts_by_category[shortcut.category].push_back(&shortcut);
388 }
389
390 // Display shortcuts by category in order
391 for (const auto& category : category_order_) {
392 auto it = shortcuts_by_category.find(category);
393 if (it != shortcuts_by_category.end() && !it->second.empty()) {
394 DrawCategorySection(category, it->second);
395 }
396 }
397
398 // Display any categories not in the order list
399 for (const auto& [category, shortcuts] : shortcuts_by_category) {
400 bool in_order = false;
401 for (const auto& ordered : category_order_) {
402 if (ordered == category) {
403 in_order = true;
404 break;
405 }
406 }
407 if (!in_order && !shortcuts.empty()) {
408 DrawCategorySection(category, shortcuts);
409 }
410 }
411
412 ImGui::EndChild();
413
414 // Footer
415 ImGui::Separator();
416 ImGui::TextDisabled("Press ? to toggle | Escape to close");
417 }
418}
419
421 const std::string& category,
422 const std::vector<const Shortcut*>& shortcuts) {
423 const auto& theme = ThemeManager::Get().GetCurrentTheme();
424 auto header_bg = ConvertColorToImVec4(theme.header);
425
426 // Category header with collapsible behavior
427 StyleColorGuard header_colors({
428 {ImGuiCol_Header, header_bg},
429 {ImGuiCol_HeaderHovered,
430 ImVec4(header_bg.x + 0.05f, header_bg.y + 0.05f,
431 header_bg.z + 0.05f, 1.0f)},
432 });
433
434 bool is_open = ImGui::CollapsingHeader(
435 category.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
436
437 if (is_open) {
438 ImGui::Indent(10.0f);
439
440 // Table for shortcuts
441 if (ImGui::BeginTable("##ShortcutTable", 3,
442 ImGuiTableFlags_SizingStretchProp |
443 ImGuiTableFlags_RowBg)) {
444 ImGui::TableSetupColumn("Shortcut", ImGuiTableColumnFlags_WidthFixed, 120.0f);
445 ImGui::TableSetupColumn("Description", ImGuiTableColumnFlags_WidthStretch);
446 ImGui::TableSetupColumn("Context", ImGuiTableColumnFlags_WidthFixed, 80.0f);
447
448 for (const auto* shortcut : shortcuts) {
449 DrawShortcutRow(*shortcut);
450 }
451
452 ImGui::EndTable();
453 }
454
455 ImGui::Unindent(10.0f);
456 ImGui::Spacing();
457 }
458}
459
461 const auto& theme = ThemeManager::Get().GetCurrentTheme();
462
463 ImGui::TableNextRow();
464
465 // Shortcut key combination
466 ImGui::TableNextColumn();
467 bool is_active = IsShortcutActiveInContext(shortcut);
468
469 // Draw keyboard shortcut badge
470 StyleColorGuard badge_colors({
471 {ImGuiCol_Button, is_active ? ImVec4(0.2f, 0.3f, 0.4f, 0.8f)
472 : ImVec4(0.15f, 0.15f, 0.15f, 0.6f)},
473 {ImGuiCol_ButtonHovered, is_active ? ImVec4(0.25f, 0.35f, 0.45f, 0.9f)
474 : ImVec4(0.2f, 0.2f, 0.2f, 0.7f)},
475 });
476 StyleVarGuard badge_vars({
477 {ImGuiStyleVar_FrameRounding, 4.0f},
478 {ImGuiStyleVar_FramePadding, ImVec2(6, 2)},
479 });
480
481 std::string display = shortcut.GetDisplayString();
482 ImGui::SmallButton(display.c_str());
483
484 // Description
485 ImGui::TableNextColumn();
486 ImVec4 text_color = is_active ? ConvertColorToImVec4(theme.text_primary)
487 : ConvertColorToImVec4(theme.text_secondary);
488 ImGui::TextColored(text_color, "%s", shortcut.description.c_str());
489
490 // Context indicator
491 ImGui::TableNextColumn();
492 if (shortcut.context != ShortcutContext::kGlobal) {
493 ImGui::TextDisabled("%s", ShortcutContextToString(shortcut.context));
494 }
495}
496
498 const Shortcut& shortcut) const {
499 if (shortcut.context == ShortcutContext::kGlobal) {
500 return true;
501 }
502 return shortcut.context == current_context_;
503}
504
505std::vector<const Shortcut*> KeyboardShortcuts::GetShortcutsInCategory(
506 const std::string& category) const {
507 std::vector<const Shortcut*> result;
508 for (const auto& [id, shortcut] : shortcuts_) {
509 if (shortcut.category == category) {
510 result.push_back(&shortcut);
511 }
512 }
513 return result;
514}
515
516std::vector<const Shortcut*> KeyboardShortcuts::GetContextShortcuts() const {
517 std::vector<const Shortcut*> result;
518 for (const auto& [id, shortcut] : shortcuts_) {
519 if (IsShortcutActiveInContext(shortcut)) {
520 result.push_back(&shortcut);
521 }
522 }
523 return result;
524}
525
526std::vector<std::string> KeyboardShortcuts::GetCategories() const {
527 std::vector<std::string> result;
528 for (const auto& [id, shortcut] : shortcuts_) {
529 bool found = false;
530 for (const auto& cat : result) {
531 if (cat == shortcut.category) {
532 found = true;
533 break;
534 }
535 }
536 if (!found) {
537 result.push_back(shortcut.category);
538 }
539 }
540 return result;
541}
542
544 std::function<void()> open_callback,
545 std::function<void()> save_callback,
546 std::function<void()> save_as_callback,
547 std::function<void()> close_callback,
548 std::function<void()> undo_callback,
549 std::function<void()> redo_callback,
550 std::function<void()> copy_callback,
551 std::function<void()> paste_callback,
552 std::function<void()> cut_callback,
553 std::function<void()> find_callback) {
554
555 // === File Shortcuts ===
556 if (open_callback) {
557 RegisterShortcut("file.open", "Open ROM/Project", ImGuiKey_O,
558 true, false, false, "File", ShortcutContext::kGlobal,
559 open_callback);
560 }
561
562 if (save_callback) {
563 RegisterShortcut("file.save", "Save", ImGuiKey_S,
564 true, false, false, "File", ShortcutContext::kGlobal,
565 save_callback);
566 }
567
568 if (save_as_callback) {
569 RegisterShortcut("file.save_as", "Save As...", ImGuiKey_S,
570 true, true, false, "File", ShortcutContext::kGlobal,
571 save_as_callback);
572 }
573
574 if (close_callback) {
575 RegisterShortcut("file.close", "Close", ImGuiKey_W,
576 true, false, false, "File", ShortcutContext::kGlobal,
577 close_callback);
578 }
579
580 // === Edit Shortcuts ===
581 if (undo_callback) {
582 RegisterShortcut("edit.undo", "Undo", ImGuiKey_Z,
583 true, false, false, "Edit", ShortcutContext::kGlobal,
584 undo_callback);
585 }
586
587 if (redo_callback) {
588 RegisterShortcut("edit.redo", "Redo", ImGuiKey_Y,
589 true, false, false, "Edit", ShortcutContext::kGlobal,
590 redo_callback);
591
592 // Also register Ctrl+Shift+Z for redo (common alternative)
593 RegisterShortcut("edit.redo_alt", "Redo", ImGuiKey_Z,
594 true, true, false, "Edit", ShortcutContext::kGlobal,
595 redo_callback);
596 }
597
598 if (copy_callback) {
599 RegisterShortcut("edit.copy", "Copy", ImGuiKey_C,
600 true, false, false, "Edit", ShortcutContext::kGlobal,
601 copy_callback);
602 }
603
604 if (paste_callback) {
605 RegisterShortcut("edit.paste", "Paste", ImGuiKey_V,
606 true, false, false, "Edit", ShortcutContext::kGlobal,
607 paste_callback);
608 }
609
610 if (cut_callback) {
611 RegisterShortcut("edit.cut", "Cut", ImGuiKey_X,
612 true, false, false, "Edit", ShortcutContext::kGlobal,
613 cut_callback);
614 }
615
616 if (find_callback) {
617 RegisterShortcut("edit.find", "Find", ImGuiKey_F,
618 true, false, false, "Edit", ShortcutContext::kGlobal,
619 find_callback);
620 }
621
622 // === View Shortcuts ===
623 RegisterShortcut("view.fullscreen", "Toggle Fullscreen", ImGuiKey_F11,
624 false, false, false, "View", ShortcutContext::kGlobal,
625 nullptr); // Placeholder - implement in EditorManager
626
627 RegisterShortcut("view.grid", "Toggle Grid", ImGuiKey_G,
628 true, false, false, "View", ShortcutContext::kGlobal,
629 nullptr); // Placeholder
630
631 RegisterShortcut("view.zoom_in", "Zoom In", ImGuiKey_Equal,
632 true, false, false, "View", ShortcutContext::kGlobal,
633 nullptr); // Placeholder
634
635 RegisterShortcut("view.zoom_out", "Zoom Out", ImGuiKey_Minus,
636 true, false, false, "View", ShortcutContext::kGlobal,
637 nullptr); // Placeholder
638
639 RegisterShortcut("view.zoom_reset", "Reset Zoom", ImGuiKey_0,
640 true, false, false, "View", ShortcutContext::kGlobal,
641 nullptr); // Placeholder
642
643 // === Navigation Shortcuts ===
644 RegisterShortcut("nav.first", "Go to First", ImGuiKey_Home,
645 false, false, false, "Navigation", ShortcutContext::kGlobal,
646 nullptr); // Placeholder
647
648 RegisterShortcut("nav.last", "Go to Last", ImGuiKey_End,
649 false, false, false, "Navigation", ShortcutContext::kGlobal,
650 nullptr); // Placeholder
651
652 RegisterShortcut("nav.prev", "Previous", ImGuiKey_PageUp,
653 false, false, false, "Navigation", ShortcutContext::kGlobal,
654 nullptr); // Placeholder
655
656 RegisterShortcut("nav.next", "Next", ImGuiKey_PageDown,
657 false, false, false, "Navigation", ShortcutContext::kGlobal,
658 nullptr); // Placeholder
659
660 // === Emulator Shortcuts ===
661 RegisterShortcut("emu.play_pause", "Play/Pause Emulator", ImGuiKey_Space,
662 false, false, false, "Editor", ShortcutContext::kEmulator,
663 nullptr); // Placeholder
664
665 RegisterShortcut("emu.reset", "Reset Emulator", ImGuiKey_R,
666 true, false, false, "Editor", ShortcutContext::kEmulator,
667 nullptr); // Placeholder
668
669 RegisterShortcut("emu.step", "Step Frame", ImGuiKey_F,
670 false, false, false, "Editor", ShortcutContext::kEmulator,
671 nullptr); // Placeholder
672
673 // === Overworld Editor Shortcuts ===
674 RegisterShortcut("ow.select_all", "Select All Tiles", ImGuiKey_A,
675 true, false, false, "Editor", ShortcutContext::kOverworld,
676 nullptr); // Placeholder
677
678 RegisterShortcut("ow.deselect", "Deselect", ImGuiKey_D,
679 true, false, false, "Editor", ShortcutContext::kOverworld,
680 nullptr); // Placeholder
681
682 // === Dungeon Editor Shortcuts ===
683 RegisterShortcut("dg.select_all", "Select All Objects", ImGuiKey_A,
684 true, false, false, "Editor", ShortcutContext::kDungeon,
685 nullptr); // Placeholder
686
687 RegisterShortcut("dg.delete", "Delete Selected", ImGuiKey_Delete,
688 false, false, false, "Editor", ShortcutContext::kDungeon,
689 nullptr); // Placeholder
690
691 RegisterShortcut("dg.duplicate", "Duplicate Selected", ImGuiKey_D,
692 true, false, false, "Editor", ShortcutContext::kDungeon,
693 nullptr); // Placeholder
694}
695
697 switch (context) {
699 return "Global";
701 return "Overworld";
703 return "Dungeon";
705 return "Graphics";
707 return "Palette";
709 return "Sprite";
711 return "Music";
713 return "Message";
715 return "Emulator";
717 return "Code";
718 default:
719 return "Unknown";
720 }
721}
722
723ShortcutContext EditorNameToContext(const std::string& editor_name) {
724 if (editor_name == "Overworld") return ShortcutContext::kOverworld;
725 if (editor_name == "Dungeon") return ShortcutContext::kDungeon;
726 if (editor_name == "Graphics") return ShortcutContext::kGraphics;
727 if (editor_name == "Palette") return ShortcutContext::kPalette;
728 if (editor_name == "Sprite") return ShortcutContext::kSprite;
729 if (editor_name == "Music") return ShortcutContext::kMusic;
730 if (editor_name == "Message") return ShortcutContext::kMessage;
731 if (editor_name == "Emulator") return ShortcutContext::kEmulator;
732 if (editor_name == "Assembly" || editor_name == "Code")
735}
736
737} // namespace gui
738} // namespace yaze
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)
std::vector< const Shortcut * > GetContextShortcuts() const
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)
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.
Definition style_guard.h:27
RAII guard for ImGui style vars.
Definition style_guard.h:68
RAII compound guard for window-level style setup.
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
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)
Definition color.h:134
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.
ShortcutContext context
std::string GetDisplayString() const
std::function< void()> action
bool Matches(ImGuiKey pressed_key, bool ctrl, bool shift, bool alt) const