yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
shortcut_configurator.cc
Go to the documentation of this file.
2
3#include <algorithm>
4
5#include "absl/functional/bind_front.h"
6#include "absl/strings/str_format.h"
29#include "core/project.h"
30#include "imgui/imgui.h"
31
32namespace yaze::editor {
33
34namespace {
35
36// Matches Global Font Scale slider in settings_panel.cc (0.5–2.0).
37constexpr float kUiFontScaleStep = 0.05f;
38constexpr float kUiFontScaleMin = 0.5f;
39constexpr float kUiFontScaleMax = 2.0f;
40
41void AdjustUiFontScaleBy(EditorManager* editor_manager, float delta) {
42 if (!editor_manager || ImGui::GetIO().WantTextInput) {
43 return;
44 }
45 float s = editor_manager->user_settings().prefs().font_global_scale + delta;
46 editor_manager->SetFontGlobalScale(
47 std::clamp(s, kUiFontScaleMin, kUiFontScaleMax));
48}
49
50void RegisterIfValid(ShortcutManager* shortcut_manager, const std::string& name,
51 const std::vector<ImGuiKey>& keys,
52 std::function<void()> callback,
54 if (!shortcut_manager || !callback) {
55 return;
56 }
57 shortcut_manager->RegisterShortcut(name, keys, std::move(callback), scope);
58}
59
60void RegisterIfValid(ShortcutManager* shortcut_manager, const std::string& name,
61 ImGuiKey key, std::function<void()> callback,
63 if (!shortcut_manager || !callback) {
64 return;
65 }
66 shortcut_manager->RegisterShortcut(name, key, std::move(callback), scope);
67}
68
69struct EditorShortcutDef {
70 std::string id;
71 std::vector<ImGuiKey> keys;
72 std::string description;
73};
74
75const std::vector<EditorShortcutDef> kMusicEditorShortcuts = {
76 {"music.play_pause", {ImGuiKey_Space}, "Play/Pause current song"},
77 {"music.stop", {ImGuiKey_Escape}, "Stop playback"},
78 {"music.speed_up", {ImGuiKey_Equal}, "Increase playback speed"},
79 {"music.speed_up_keypad",
80 {ImGuiKey_KeypadAdd},
81 "Increase playback speed (keypad)"},
82 {"music.speed_down", {ImGuiKey_Minus}, "Decrease playback speed"},
83 {"music.speed_down_keypad",
84 {ImGuiKey_KeypadSubtract},
85 "Decrease playback speed (keypad)"},
86};
87
88const std::vector<EditorShortcutDef> kDungeonEditorShortcuts = {
89 {"dungeon.object.select_tool", {ImGuiKey_S}, "Select tool"},
90 {"dungeon.object.place_tool", {ImGuiKey_P}, "Place tool"},
91 {"dungeon.object.delete_tool", {ImGuiKey_D}, "Delete tool"},
92 {"dungeon.object.next_object", {ImGuiKey_RightBracket}, "Next object"},
93 {"dungeon.object.prev_object", {ImGuiKey_LeftBracket}, "Previous object"},
94 {"dungeon.object.copy", {ImGuiMod_Ctrl, ImGuiKey_C}, "Copy selection"},
95 {"dungeon.object.paste", {ImGuiMod_Ctrl, ImGuiKey_V}, "Paste selection"},
96 {"dungeon.object.delete", {ImGuiKey_Delete}, "Delete selection"},
97};
98
99const std::vector<EditorShortcutDef> kOverworldShortcuts = {
100 {"overworld.brush_toggle", {ImGuiKey_B}, "Toggle brush"},
101 {"overworld.fill", {ImGuiKey_F}, "Fill tool"},
102 {"overworld.next_tile", {ImGuiKey_RightBracket}, "Next tile"},
103 {"overworld.prev_tile", {ImGuiKey_LeftBracket}, "Previous tile"},
104};
105
106const std::vector<EditorShortcutDef> kGraphicsShortcuts = {
107 // Sheet navigation
108 {"graphics.next_sheet", {ImGuiKey_PageDown}, "Next sheet"},
109 {"graphics.prev_sheet", {ImGuiKey_PageUp}, "Previous sheet"},
110
111 // Tool selection shortcuts
112 {"graphics.tool.select", {ImGuiKey_V}, "Select tool"},
113 {"graphics.tool.pencil", {ImGuiKey_B}, "Pencil tool"},
114 {"graphics.tool.brush", {ImGuiKey_P}, "Brush tool"},
115 {"graphics.tool.eraser", {ImGuiKey_E}, "Eraser tool"},
116 {"graphics.tool.fill", {ImGuiKey_G}, "Fill tool"},
117 {"graphics.tool.line", {ImGuiKey_L}, "Line tool"},
118 {"graphics.tool.rectangle", {ImGuiKey_R}, "Rectangle tool"},
119 {"graphics.tool.eyedropper", {ImGuiKey_I}, "Eyedropper tool"},
120
121 // Zoom controls
122 {"graphics.zoom_in", {ImGuiKey_Equal}, "Zoom in"},
123 {"graphics.zoom_in_keypad", {ImGuiKey_KeypadAdd}, "Zoom in (keypad)"},
124 {"graphics.zoom_out", {ImGuiKey_Minus}, "Zoom out"},
125 {"graphics.zoom_out_keypad",
126 {ImGuiKey_KeypadSubtract},
127 "Zoom out (keypad)"},
128
129 // View toggles
130 {"graphics.toggle_grid", {ImGuiMod_Ctrl, ImGuiKey_G}, "Toggle grid"},
131};
132
133} // namespace
134
135void ConfigureEditorShortcuts(const ShortcutDependencies& deps,
136 ShortcutManager* shortcut_manager) {
137 if (!shortcut_manager) {
138 return;
139 }
140
141 auto* editor_manager = deps.editor_manager;
142 auto* ui_coordinator = deps.ui_coordinator;
143 auto* popup_manager = deps.popup_manager;
144 auto* window_manager = deps.window_manager;
145
146 // Toggle activity bar (48px icon strip) visibility
148 shortcut_manager, "view.toggle_activity_bar", {ImGuiMod_Ctrl, ImGuiKey_B},
149 [window_manager]() {
150 if (window_manager) {
151 window_manager->ToggleSidebarVisibility();
152 }
153 },
155
156 // Toggle side panel (250px expanded panel) expansion
158 shortcut_manager, "view.toggle_side_panel",
159 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_E},
160 [window_manager]() {
161 if (window_manager) {
162 window_manager->ToggleSidebarExpanded();
163 }
164 },
166
167 // Interface / font scale (Ctrl+/- on Windows/Linux, Cmd+/- on macOS).
169 shortcut_manager, "ui.font_scale_increase",
170 {ImGuiMod_Ctrl, ImGuiKey_Equal},
171 [editor_manager]() {
172 AdjustUiFontScaleBy(editor_manager, kUiFontScaleStep);
173 },
175
177 shortcut_manager, "ui.font_scale_increase_keypad",
178 {ImGuiMod_Ctrl, ImGuiKey_KeypadAdd},
179 [editor_manager]() {
180 AdjustUiFontScaleBy(editor_manager, kUiFontScaleStep);
181 },
183
185 shortcut_manager, "ui.font_scale_decrease",
186 {ImGuiMod_Ctrl, ImGuiKey_Minus},
187 [editor_manager]() {
188 AdjustUiFontScaleBy(editor_manager, -kUiFontScaleStep);
189 },
191
193 shortcut_manager, "ui.font_scale_decrease_keypad",
194 {ImGuiMod_Ctrl, ImGuiKey_KeypadSubtract},
195 [editor_manager]() {
196 AdjustUiFontScaleBy(editor_manager, -kUiFontScaleStep);
197 },
199
201 shortcut_manager, "ui.font_scale_reset", {ImGuiMod_Ctrl, ImGuiKey_0},
202 [editor_manager]() {
203 if (!editor_manager || ImGui::GetIO().WantTextInput) {
204 return;
205 }
206 editor_manager->SetFontGlobalScale(1.0f);
207 },
209
211 shortcut_manager, "Open", {ImGuiMod_Ctrl, ImGuiKey_O},
212 [editor_manager]() {
213 if (editor_manager) {
214 editor_manager->LoadRom();
215 }
216 },
218
219 RegisterIfValid(shortcut_manager, "Save", {ImGuiMod_Ctrl, ImGuiKey_S},
220 [editor_manager]() {
221 if (editor_manager) {
222 editor_manager->SaveRom();
223 }
224 });
225
227 shortcut_manager, "Save As", {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_S},
228 [editor_manager]() {
229 if (editor_manager) {
230 // Use project-aware default filename when possible
231 std::string filename =
232 editor_manager->GetCurrentRom()
233 ? editor_manager->GetCurrentRom()->filename()
234 : "";
235 editor_manager->SaveRomAs(filename);
236 }
237 },
239
241 shortcut_manager, "Close ROM", {ImGuiMod_Ctrl, ImGuiKey_W},
242 [editor_manager]() {
243 if (editor_manager && editor_manager->GetCurrentRom()) {
244 editor_manager->GetCurrentRom()->Close();
245 }
246 },
248
250 shortcut_manager, "Quit", {ImGuiMod_Ctrl, ImGuiKey_Q},
251 [editor_manager]() {
252 if (editor_manager) {
253 editor_manager->Quit();
254 }
255 },
257
259 shortcut_manager, "Undo", {ImGuiMod_Ctrl, ImGuiKey_Z},
260 [editor_manager]() {
261 if (editor_manager && editor_manager->GetCurrentEditor()) {
262 editor_manager->GetCurrentEditor()->Undo();
263 }
264 },
266
268 shortcut_manager, "Redo", {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_Z},
269 [editor_manager]() {
270 if (editor_manager && editor_manager->GetCurrentEditor()) {
271 editor_manager->GetCurrentEditor()->Redo();
272 }
273 },
275
277 shortcut_manager, "Cut", {ImGuiMod_Ctrl, ImGuiKey_X},
278 [editor_manager]() {
279 if (editor_manager && editor_manager->GetCurrentEditor()) {
280 editor_manager->GetCurrentEditor()->Cut();
281 }
282 },
284
286 shortcut_manager, "Copy", {ImGuiMod_Ctrl, ImGuiKey_C},
287 [editor_manager]() {
288 if (editor_manager && editor_manager->GetCurrentEditor()) {
289 editor_manager->GetCurrentEditor()->Copy();
290 }
291 },
293
295 shortcut_manager, "Paste", {ImGuiMod_Ctrl, ImGuiKey_V},
296 [editor_manager]() {
297 if (editor_manager && editor_manager->GetCurrentEditor()) {
298 editor_manager->GetCurrentEditor()->Paste();
299 }
300 },
302
304 shortcut_manager, "Find", {ImGuiMod_Ctrl, ImGuiKey_F},
305 [editor_manager]() {
306 if (editor_manager && editor_manager->GetCurrentEditor()) {
307 editor_manager->GetCurrentEditor()->Find();
308 }
309 },
311
313 shortcut_manager, "Command Palette",
314 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_P},
315 [ui_coordinator]() {
316 if (ui_coordinator) {
317 ui_coordinator->ShowCommandPalette();
318 }
319 },
321
323 shortcut_manager, "Global Search",
324 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_K},
325 [ui_coordinator]() {
326 if (ui_coordinator) {
327 ui_coordinator->ShowGlobalSearch();
328 }
329 },
331
333 shortcut_manager, "Load Last ROM", {ImGuiMod_Ctrl, ImGuiKey_R},
334 [editor_manager]() {
336 if (!recent.GetRecentFiles().empty() && editor_manager) {
337 editor_manager->OpenRomOrProject(recent.GetRecentFiles().front());
338 }
339 },
341
343 shortcut_manager, "Show About", ImGuiKey_F1,
344 [popup_manager]() {
345 if (popup_manager) {
346 popup_manager->Show("About");
347 }
348 },
350
351 auto register_editor_shortcut = [&](EditorType type, ImGuiKey key) {
352 RegisterIfValid(shortcut_manager,
353 absl::StrFormat("switch.%d", static_cast<int>(type)),
354 {ImGuiMod_Ctrl, key}, [editor_manager, type]() {
355 if (editor_manager) {
356 editor_manager->SwitchToEditor(type);
357 }
358 });
359 };
360
361 register_editor_shortcut(EditorType::kOverworld, ImGuiKey_1);
362 register_editor_shortcut(EditorType::kDungeon, ImGuiKey_2);
363 register_editor_shortcut(EditorType::kGraphics, ImGuiKey_3);
364 register_editor_shortcut(EditorType::kSprite, ImGuiKey_4);
365 register_editor_shortcut(EditorType::kMessage, ImGuiKey_5);
366 register_editor_shortcut(EditorType::kMusic, ImGuiKey_6);
367 register_editor_shortcut(EditorType::kPalette, ImGuiKey_7);
368 register_editor_shortcut(EditorType::kScreen, ImGuiKey_8);
369 register_editor_shortcut(EditorType::kAssembly, ImGuiKey_9);
370 register_editor_shortcut(EditorType::kSettings, ImGuiKey_0);
371
372 // ============================================================================
373 // Editor Switch Commands (command palette with friendly names)
374 // ============================================================================
375 auto register_editor_command = [&](EditorType type, const std::string& name) {
376 shortcut_manager->RegisterCommand(
377 absl::StrFormat("Switch to %s Editor", name), [editor_manager, type]() {
378 if (editor_manager) {
379 editor_manager->SwitchToEditor(type);
380 }
381 });
382 };
383
384 register_editor_command(EditorType::kOverworld, "Overworld");
385 register_editor_command(EditorType::kDungeon, "Dungeon");
386 register_editor_command(EditorType::kGraphics, "Graphics");
387 register_editor_command(EditorType::kSprite, "Sprite");
388 register_editor_command(EditorType::kMessage, "Message");
389 register_editor_command(EditorType::kMusic, "Music");
390 register_editor_command(EditorType::kPalette, "Palette");
391 register_editor_command(EditorType::kScreen, "Screen");
392 register_editor_command(EditorType::kAssembly, "Assembly");
393 register_editor_command(EditorType::kSettings, "Settings");
394
395 // Editor-scoped Music shortcuts (toggle playback, speed controls)
396 if (editor_manager) {
397 for (const auto& def : kMusicEditorShortcuts) {
399 shortcut_manager, def.id, def.keys,
400 [editor_manager, id = def.id]() {
401 if (!editor_manager)
402 return;
403 auto* current_editor = editor_manager->GetCurrentEditor();
404 if (!current_editor ||
405 current_editor->type() != EditorType::kMusic) {
406 return;
407 }
408 auto* editor_set = editor_manager->GetCurrentEditorSet();
409 auto* music_editor =
410 editor_set ? editor_set->GetMusicEditor() : nullptr;
411 if (!music_editor)
412 return;
413
414 if (id == "music.play_pause") {
415 music_editor->TogglePlayPause();
416 } else if (id == "music.stop") {
417 music_editor->StopPlayback();
418 } else if (id == "music.speed_up" ||
419 id == "music.speed_up_keypad") {
420 music_editor->SpeedUp();
421 } else if (id == "music.speed_down" ||
422 id == "music.speed_down_keypad") {
423 music_editor->SlowDown();
424 }
425 },
427 }
428 }
429
430 // Editor-scoped Dungeon shortcuts (object tools)
431 if (editor_manager) {
432 for (const auto& def : kDungeonEditorShortcuts) {
434 shortcut_manager, def.id, def.keys,
435 [editor_manager, id = def.id]() {
436 if (!editor_manager)
437 return;
438 auto* current_editor = editor_manager->GetCurrentEditor();
439 if (!current_editor ||
440 current_editor->type() != EditorType::kDungeon) {
441 return;
442 }
443 auto* editor_set = editor_manager->GetCurrentEditorSet();
444 auto* dungeon_editor =
445 editor_set ? editor_set->GetDungeonEditor() : nullptr;
446 if (!dungeon_editor)
447 return;
448 auto* object_selector = dungeon_editor->object_selector_panel();
449 auto* object_editor = dungeon_editor->object_editor_content();
450
451 if (id == "dungeon.object.select_tool") {
452 // Unified mode: cancel placement to switch to selection
453 if (object_selector) {
454 object_selector->CancelPlacement();
455 }
456 } else if (id == "dungeon.object.place_tool") {
457 // Unified mode: handled by object selector click
458 // No-op (mode is controlled by selecting an object)
459 } else if (id == "dungeon.object.delete_tool") {
460 if (object_editor) {
461 object_editor->DeleteSelectedObjects();
462 }
463 } else if (id == "dungeon.object.next_object") {
464 if (object_editor) {
465 object_editor->CycleObjectSelection(1);
466 }
467 } else if (id == "dungeon.object.prev_object") {
468 if (object_editor) {
469 object_editor->CycleObjectSelection(-1);
470 }
471 } else if (id == "dungeon.object.copy") {
472 if (object_editor) {
473 object_editor->CopySelectedObjects();
474 }
475 } else if (id == "dungeon.object.paste") {
476 if (object_editor) {
477 object_editor->PasteObjects();
478 }
479 } else if (id == "dungeon.object.delete") {
480 if (object_editor) {
481 object_editor->DeleteSelectedObjects();
482 }
483 }
484 },
486 }
487 }
488
489 // Editor-scoped Overworld shortcuts (basic tools)
490 if (editor_manager) {
491 for (const auto& def : kOverworldShortcuts) {
493 shortcut_manager, def.id, def.keys,
494 [editor_manager, id = def.id]() {
495 if (!editor_manager)
496 return;
497 auto* current_editor = editor_manager->GetCurrentEditor();
498 if (!current_editor ||
499 current_editor->type() != EditorType::kOverworld) {
500 return;
501 }
502 auto* editor_set = editor_manager->GetCurrentEditorSet();
503 auto* overworld_editor =
504 editor_set ? editor_set->GetOverworldEditor() : nullptr;
505 if (!overworld_editor)
506 return;
507
508 if (id == "overworld.brush_toggle") {
509 overworld_editor->ToggleBrushTool();
510 } else if (id == "overworld.fill") {
511 overworld_editor->ActivateFillTool();
512 } else if (id == "overworld.next_tile") {
513 overworld_editor->CycleTileSelection(1);
514 } else if (id == "overworld.prev_tile") {
515 overworld_editor->CycleTileSelection(-1);
516 }
517 },
518 Shortcut::Scope::kEditor);
519 }
520 }
521
522 // Editor-scoped Graphics shortcuts (sheet navigation)
523 if (editor_manager) {
524 for (const auto& def : kGraphicsShortcuts) {
526 shortcut_manager, def.id, def.keys,
527 [editor_manager, id = def.id]() {
528 if (!editor_manager)
529 return;
530 auto* current_editor = editor_manager->GetCurrentEditor();
531 if (!current_editor ||
532 current_editor->type() != EditorType::kGraphics) {
533 return;
534 }
535 auto* editor_set = editor_manager->GetCurrentEditorSet();
536 auto* graphics_editor =
537 editor_set ? editor_set->GetGraphicsEditor() : nullptr;
538 if (!graphics_editor)
539 return;
540
541 if (id == "graphics.next_sheet") {
542 graphics_editor->NextSheet();
543 } else if (id == "graphics.prev_sheet") {
544 graphics_editor->PrevSheet();
545 }
546 },
547 Shortcut::Scope::kEditor);
548 }
549 }
550
552 shortcut_manager, "Editor Selection", {ImGuiMod_Ctrl, ImGuiKey_E},
553 [ui_coordinator]() {
554 if (ui_coordinator) {
555 ui_coordinator->ShowEditorSelection();
556 }
557 },
558 Shortcut::Scope::kGlobal);
559
561 shortcut_manager, "Panel Browser",
562 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_B},
563 [ui_coordinator]() {
564 if (ui_coordinator) {
565 ui_coordinator->ShowWindowBrowser();
566 }
567 },
568 Shortcut::Scope::kGlobal);
570 shortcut_manager, "Window Browser",
571 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_B},
572 [ui_coordinator]() {
573 if (ui_coordinator) {
574 ui_coordinator->ShowWindowBrowser();
575 }
576 },
577 Shortcut::Scope::kGlobal);
579 shortcut_manager, "Panel Browser (Alt)",
580 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_P},
581 [ui_coordinator]() {
582 if (ui_coordinator) {
583 ui_coordinator->ShowWindowBrowser();
584 }
585 },
586 Shortcut::Scope::kGlobal);
588 shortcut_manager, "Window Browser (Alt)",
589 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_P},
590 [ui_coordinator]() {
591 if (ui_coordinator) {
592 ui_coordinator->ShowWindowBrowser();
593 }
594 },
595 Shortcut::Scope::kGlobal);
596
598 shortcut_manager, "View: Previous Right Panel",
599 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_LeftBracket},
600 [editor_manager]() {
601 if (!editor_manager) {
602 return;
603 }
604 if (auto* right_panel = editor_manager->right_drawer_manager()) {
605 right_panel->CycleToPreviousDrawer();
606 }
607 },
608 Shortcut::Scope::kGlobal);
610 shortcut_manager, "View: Previous Right Drawer",
611 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_LeftBracket},
612 [editor_manager]() {
613 if (!editor_manager) {
614 return;
615 }
616 if (auto* right_drawer = editor_manager->right_drawer_manager()) {
617 right_drawer->CycleToPreviousDrawer();
618 }
619 },
620 Shortcut::Scope::kGlobal);
621
623 shortcut_manager, "View: Next Right Panel",
624 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_RightBracket},
625 [editor_manager]() {
626 if (!editor_manager) {
627 return;
628 }
629 if (auto* right_panel = editor_manager->right_drawer_manager()) {
630 right_panel->CycleToNextDrawer();
631 }
632 },
633 Shortcut::Scope::kGlobal);
635 shortcut_manager, "View: Next Right Drawer",
636 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_RightBracket},
637 [editor_manager]() {
638 if (!editor_manager) {
639 return;
640 }
641 if (auto* right_drawer = editor_manager->right_drawer_manager()) {
642 right_drawer->CycleToNextDrawer();
643 }
644 },
645 Shortcut::Scope::kGlobal);
646
647 if (window_manager) {
648 // Note: Using Ctrl+Alt for panel shortcuts to avoid conflicts with Save As
649 // (Ctrl+Shift+S)
651 shortcut_manager, "Show Dungeon Panels",
652 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_D},
653 [window_manager]() {
654 window_manager->ShowAllWindowsInCategory(0, "Dungeon");
655 },
656 Shortcut::Scope::kEditor);
658 shortcut_manager, "Show Dungeon Windows",
659 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_D},
660 [window_manager]() {
661 window_manager->ShowAllWindowsInCategory(0, "Dungeon");
662 },
663 Shortcut::Scope::kEditor);
665 shortcut_manager, "Show Graphics Panels",
666 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_G},
667 [window_manager]() {
668 window_manager->ShowAllWindowsInCategory(0, "Graphics");
669 },
670 Shortcut::Scope::kEditor);
672 shortcut_manager, "Show Graphics Windows",
673 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_G},
674 [window_manager]() {
675 window_manager->ShowAllWindowsInCategory(0, "Graphics");
676 },
677 Shortcut::Scope::kEditor);
679 shortcut_manager, "Show Screen Panels",
680 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_S},
681 [window_manager]() {
682 window_manager->ShowAllWindowsInCategory(0, "Screen");
683 },
684 Shortcut::Scope::kEditor);
686 shortcut_manager, "Show Screen Windows",
687 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_S},
688 [window_manager]() {
689 window_manager->ShowAllWindowsInCategory(0, "Screen");
690 },
691 Shortcut::Scope::kEditor);
692 }
693
694#ifdef YAZE_BUILD_AGENT_UI
695 RegisterIfValid(shortcut_manager, "Agent Editor",
696 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_A},
697 [editor_manager]() {
698 if (editor_manager) {
699 editor_manager->ShowAIAgent();
700 }
701 });
702
703 RegisterIfValid(shortcut_manager, "Agent Sidebar",
704 {ImGuiMod_Ctrl, ImGuiKey_H}, [editor_manager]() {
705 if (editor_manager) {
706 editor_manager->ShowChatHistory();
707 }
708 });
709
710 RegisterIfValid(shortcut_manager, "Proposal Drawer",
711 {ImGuiMod_Ctrl, ImGuiMod_Shift,
712 ImGuiKey_R}, // Changed from Ctrl+P to Ctrl+Shift+R
713 [editor_manager]() {
714 if (editor_manager) {
715 editor_manager->ShowProposalDrawer();
716 }
717 });
718#endif
719
720 // ============================================================================
721 // Layout Presets and Profiles (command palette only - no keyboard shortcuts)
722 // ============================================================================
723 shortcut_manager->RegisterCommand("Layout Profile: Code", [editor_manager]() {
724 if (editor_manager) {
725 editor_manager->ApplyLayoutProfile("code");
726 }
727 });
728 shortcut_manager->RegisterCommand(
729 "Layout Profile: Debug", [editor_manager]() {
730 if (editor_manager) {
731 editor_manager->ApplyLayoutProfile("debug");
732 }
733 });
734 shortcut_manager->RegisterCommand(
735 "Layout Profile: Mapping", [editor_manager]() {
736 if (editor_manager) {
737 editor_manager->ApplyLayoutProfile("mapping");
738 }
739 });
740 shortcut_manager->RegisterCommand("Layout Profile: Chat", [editor_manager]() {
741 if (editor_manager) {
742 editor_manager->ApplyLayoutProfile("chat");
743 }
744 });
745 shortcut_manager->RegisterCommand(
746 "Layout Snapshot: Capture", [editor_manager]() {
747 if (editor_manager) {
748 editor_manager->CaptureTemporaryLayoutSnapshot();
749 }
750 });
751 shortcut_manager->RegisterCommand(
752 "Layout Snapshot: Restore", [editor_manager]() {
753 if (editor_manager) {
754 editor_manager->RestoreTemporaryLayoutSnapshot();
755 }
756 });
757 shortcut_manager->RegisterCommand(
758 "Layout Snapshot: Clear", [editor_manager]() {
759 if (editor_manager) {
760 editor_manager->ClearTemporaryLayoutSnapshot();
761 }
762 });
763
764 shortcut_manager->RegisterCommand(
765 "Layout: Apply Minimal Preset", [editor_manager]() {
766 if (editor_manager) {
767 editor_manager->ApplyLayoutPreset("Minimal");
768 }
769 });
770 shortcut_manager->RegisterCommand(
771 "Layout: Apply Developer Preset", [editor_manager]() {
772 if (editor_manager) {
773 editor_manager->ApplyLayoutPreset("Developer");
774 }
775 });
776 shortcut_manager->RegisterCommand(
777 "Layout: Apply Designer Preset", [editor_manager]() {
778 if (editor_manager) {
779 editor_manager->ApplyLayoutPreset("Designer");
780 }
781 });
782 shortcut_manager->RegisterCommand(
783 "Layout: Apply Modder Preset", [editor_manager]() {
784 if (editor_manager) {
785 editor_manager->ApplyLayoutPreset("Modder");
786 }
787 });
788 shortcut_manager->RegisterCommand(
789 "Layout: Apply Overworld Expert Preset", [editor_manager]() {
790 if (editor_manager) {
791 editor_manager->ApplyLayoutPreset("Overworld Expert");
792 }
793 });
794 shortcut_manager->RegisterCommand(
795 "Layout: Apply Dungeon Expert Preset", [editor_manager]() {
796 if (editor_manager) {
797 editor_manager->ApplyLayoutPreset("Dungeon Expert");
798 }
799 });
800 shortcut_manager->RegisterCommand(
801 "Layout: Apply Testing Preset", [editor_manager]() {
802 if (editor_manager) {
803 editor_manager->ApplyLayoutPreset("Testing");
804 }
805 });
806 shortcut_manager->RegisterCommand(
807 "Layout: Apply Audio Preset", [editor_manager]() {
808 if (editor_manager) {
809 editor_manager->ApplyLayoutPreset("Audio");
810 }
811 });
812 shortcut_manager->RegisterCommand(
813 "Layout: Reset Current Editor", [editor_manager]() {
814 if (editor_manager) {
815 editor_manager->ResetCurrentEditorLayout();
816 }
817 });
818
819 // ============================================================================
820 // Right Drawer / Panel Toggle Commands (command palette only)
821 // ============================================================================
822 if (editor_manager) {
823 using DrawerType = RightDrawerManager::DrawerType;
824 auto* right_drawer_manager = editor_manager->right_drawer_manager();
825 if (right_drawer_manager) {
826 struct DrawerCmd {
827 const char* label;
828 DrawerType type;
829 };
830 DrawerCmd drawer_cmds[] = {
831 {"View: Toggle AI Agent Panel", DrawerType::kAgentChat},
832 {"View: Toggle AI Agent Drawer", DrawerType::kAgentChat},
833 {"View: Toggle Proposals Panel", DrawerType::kProposals},
834 {"View: Toggle Proposals Drawer", DrawerType::kProposals},
835 {"View: Toggle Settings Panel", DrawerType::kSettings},
836 {"View: Toggle Settings Drawer", DrawerType::kSettings},
837 {"View: Toggle Help Panel", DrawerType::kHelp},
838 {"View: Toggle Help Drawer", DrawerType::kHelp},
839 {"View: Toggle Notifications", DrawerType::kNotifications},
840 {"View: Toggle Notifications Drawer", DrawerType::kNotifications},
841 {"View: Toggle Properties Panel", DrawerType::kProperties},
842 {"View: Toggle Properties Drawer", DrawerType::kProperties},
843 {"View: Toggle Project Panel", DrawerType::kProject},
844 {"View: Toggle Project Drawer", DrawerType::kProject},
845 };
846 for (const auto& cmd : drawer_cmds) {
847 shortcut_manager->RegisterCommand(
848 cmd.label, [right_drawer_manager, drawer_type = cmd.type]() {
849 right_drawer_manager->ToggleDrawer(drawer_type);
850 });
851 }
852 shortcut_manager->RegisterCommand(
853 "View: Previous Right Panel", [right_drawer_manager]() {
854 right_drawer_manager->CycleToPreviousDrawer();
855 });
856 shortcut_manager->RegisterCommand(
857 "View: Previous Right Drawer", [right_drawer_manager]() {
858 right_drawer_manager->CycleToPreviousDrawer();
859 });
860 shortcut_manager->RegisterCommand(
861 "View: Next Right Panel", [right_drawer_manager]() {
862 right_drawer_manager->CycleToNextDrawer();
863 });
864 shortcut_manager->RegisterCommand(
865 "View: Next Right Drawer", [right_drawer_manager]() {
866 right_drawer_manager->CycleToNextDrawer();
867 });
868 }
869 }
870
871 // ============================================================================
872 // Window + Panel Visibility Commands (command palette only)
873 // ============================================================================
874 if (window_manager) {
875 auto categories = window_manager->GetAllCategories();
876 int session_id = 0; // Default session for command registration
877
878 shortcut_manager->RegisterCommand(
879 "View: Show Panel Browser",
880 [window_manager]() { window_manager->TriggerShowWindowBrowser(); });
881 shortcut_manager->RegisterCommand(
882 "View: Show Window Browser",
883 [window_manager]() { window_manager->TriggerShowWindowBrowser(); });
884
885 for (const auto& category : categories) {
886 auto windows = window_manager->GetWindowsInCategory(session_id, category);
887 for (const auto& window : windows) {
888 const std::string window_id = window.card_id;
889 const std::string display_name = window.display_name;
890
891 shortcut_manager->RegisterCommand(
892 absl::StrFormat("View: Show %s", display_name),
893 [window_manager, window_id]() {
894 if (window_manager) {
895 window_manager->OpenWindow(0, window_id);
896 }
897 });
898 shortcut_manager->RegisterCommand(
899 absl::StrFormat("View: Hide %s", display_name),
900 [window_manager, window_id]() {
901 if (window_manager) {
902 window_manager->CloseWindow(0, window_id);
903 }
904 });
905 shortcut_manager->RegisterCommand(
906 absl::StrFormat("View: Toggle %s", display_name),
907 [window_manager, window_id]() {
908 if (window_manager) {
909 window_manager->ToggleWindow(0, window_id);
910 }
911 });
912
913 shortcut_manager->RegisterCommand(
914 absl::StrFormat("View: Open %s Window", display_name),
915 [window_manager, window_id]() {
916 if (window_manager) {
917 window_manager->OpenWindow(0, window_id);
918 }
919 });
920 shortcut_manager->RegisterCommand(
921 absl::StrFormat("View: Close %s Window", display_name),
922 [window_manager, window_id]() {
923 if (window_manager) {
924 window_manager->CloseWindow(0, window_id);
925 }
926 });
927 shortcut_manager->RegisterCommand(
928 absl::StrFormat("View: Toggle %s Window", display_name),
929 [window_manager, window_id]() {
930 if (window_manager) {
931 window_manager->ToggleWindow(0, window_id);
932 }
933 });
934 }
935
936 shortcut_manager->RegisterCommand(
937 absl::StrFormat("View: Show All %s Panels", category),
938 [window_manager, category]() {
939 if (window_manager) {
940 window_manager->ShowAllWindowsInCategory(0, category);
941 }
942 });
943 shortcut_manager->RegisterCommand(
944 absl::StrFormat("View: Hide All %s Panels", category),
945 [window_manager, category]() {
946 if (window_manager) {
947 window_manager->HideAllWindowsInCategory(0, category);
948 }
949 });
950 shortcut_manager->RegisterCommand(
951 absl::StrFormat("View: Show All %s Windows", category),
952 [window_manager, category]() {
953 if (window_manager) {
954 window_manager->ShowAllWindowsInCategory(0, category);
955 }
956 });
957 shortcut_manager->RegisterCommand(
958 absl::StrFormat("View: Hide All %s Windows", category),
959 [window_manager, category]() {
960 if (window_manager) {
961 window_manager->HideAllWindowsInCategory(0, category);
962 }
963 });
964 }
965 }
966}
967
968void ConfigureMenuShortcuts(const ShortcutDependencies& deps,
969 ShortcutManager* shortcut_manager) {
970 if (!shortcut_manager) {
971 return;
972 }
973
974 auto* menu_orchestrator = deps.menu_orchestrator;
975 auto* session_coordinator = deps.session_coordinator;
976 auto* workspace_manager = deps.workspace_manager;
977
978 RegisterIfValid(shortcut_manager, "New Session",
979 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_N},
980 [session_coordinator]() {
981 if (session_coordinator) {
982 session_coordinator->CreateNewSession();
983 }
984 });
985
986 RegisterIfValid(shortcut_manager, "Duplicate Session",
987 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_D},
988 [session_coordinator]() {
989 if (session_coordinator) {
990 session_coordinator->DuplicateCurrentSession();
991 }
992 });
993
994 RegisterIfValid(shortcut_manager, "Close Session",
995 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_W},
996 [session_coordinator]() {
997 if (session_coordinator) {
998 session_coordinator->CloseCurrentSession();
999 }
1000 });
1001
1002 RegisterIfValid(shortcut_manager, "Session Switcher",
1003 {ImGuiMod_Ctrl, ImGuiKey_Tab}, [session_coordinator]() {
1004 if (session_coordinator) {
1005 session_coordinator->ShowSessionSwitcher();
1006 }
1007 });
1008
1009 RegisterIfValid(shortcut_manager, "Save Layout",
1010 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_L},
1011 [workspace_manager]() {
1012 if (workspace_manager) {
1013 workspace_manager->SaveWorkspaceLayout();
1014 }
1015 });
1016
1017 RegisterIfValid(shortcut_manager, "Load Layout",
1018 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_O},
1019 [workspace_manager]() {
1020 if (workspace_manager) {
1021 workspace_manager->LoadWorkspaceLayout();
1022 }
1023 });
1024
1025 // Note: Changed from Ctrl+Shift+R to Ctrl+Alt+R to avoid conflict with
1026 // Proposal Drawer
1027 RegisterIfValid(shortcut_manager, "Reset Layout",
1028 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_R},
1029 [workspace_manager]() {
1030 if (workspace_manager) {
1031 workspace_manager->ResetWorkspaceLayout();
1032 }
1033 });
1034
1035 RegisterIfValid(shortcut_manager, "Maximize Window", ImGuiKey_F11,
1036 [workspace_manager]() {
1037 if (workspace_manager) {
1038 workspace_manager->MaximizeCurrentWindow();
1039 }
1040 });
1041
1042#ifdef YAZE_ENABLE_TESTING
1043 RegisterIfValid(shortcut_manager, "Test Dashboard",
1044 {ImGuiMod_Ctrl, ImGuiKey_T}, [menu_orchestrator]() {
1045 if (menu_orchestrator) {
1046 menu_orchestrator->OnShowTestDashboard();
1047 }
1048 });
1049#endif
1050}
1051
1052void ConfigurePanelShortcuts(const ShortcutDependencies& deps,
1053 ShortcutManager* shortcut_manager) {
1054 if (!shortcut_manager || !deps.window_manager) {
1055 return;
1056 }
1057
1058 auto* window_manager = deps.window_manager;
1059 auto* user_settings = deps.user_settings;
1060 int session_id = deps.session_coordinator
1061 ? deps.session_coordinator->GetActiveSessionIndex()
1062 : 0;
1063
1064 // Get all categories and panels
1065 auto categories = window_manager->GetAllCategories();
1066
1067 for (const auto& category : categories) {
1068 auto panels = window_manager->GetWindowsInCategory(session_id, category);
1069
1070 for (const auto& panel : panels) {
1071 std::string shortcut_string;
1072
1073 // Check for user-defined shortcut first
1074 if (user_settings) {
1075 auto it = user_settings->prefs().panel_shortcuts.find(panel.card_id);
1076 if (it != user_settings->prefs().panel_shortcuts.end()) {
1077 shortcut_string = it->second;
1078 }
1079 }
1080
1081 // Fall back to default shortcut_hint
1082 if (shortcut_string.empty() && !panel.shortcut_hint.empty()) {
1083 shortcut_string = panel.shortcut_hint;
1084 }
1085
1086 // If we have a shortcut, parse and register it
1087 if (!shortcut_string.empty()) {
1088 auto keys = ParseShortcut(shortcut_string);
1089 if (!keys.empty()) {
1090 std::string panel_id_copy = panel.card_id;
1091 // Toggle panel visibility shortcut
1092 if (panel.shortcut_scope == WindowDescriptor::ShortcutScope::kPanel) {
1093 std::string toggle_id = "view.toggle." + panel.card_id;
1094 RegisterIfValid(shortcut_manager, toggle_id, keys,
1095 [window_manager, panel_id_copy, session_id]() {
1096 window_manager->ToggleWindow(session_id,
1097 panel_id_copy);
1098 });
1099 }
1100 }
1101 }
1102 }
1103 }
1104}
1105
1106} // namespace yaze::editor
static RecentFilesManager & GetInstance()
Definition project.h:425
void RegisterIfValid(ShortcutManager *shortcut_manager, const std::string &name, const std::vector< ImGuiKey > &keys, std::function< void()> callback, Shortcut::Scope scope=Shortcut::Scope::kGlobal)
void AdjustUiFontScaleBy(EditorManager *editor_manager, float delta)
Editors are the view controllers for the application.
void ConfigureMenuShortcuts(const ShortcutDependencies &deps, ShortcutManager *shortcut_manager)
std::vector< ImGuiKey > ParseShortcut(const std::string &shortcut)
void ConfigurePanelShortcuts(const ShortcutDependencies &deps, ShortcutManager *shortcut_manager)
Register configurable panel shortcuts from user settings.
void ConfigureEditorShortcuts(const ShortcutDependencies &deps, ShortcutManager *shortcut_manager)