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
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
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
147 RegisterIfValid(
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
157 RegisterIfValid(
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).
168 RegisterIfValid(
169 shortcut_manager, "ui.font_scale_increase",
170 {ImGuiMod_Ctrl, ImGuiKey_Equal},
171 [editor_manager]() {
172 AdjustUiFontScaleBy(editor_manager, kUiFontScaleStep);
173 },
175
176 RegisterIfValid(
177 shortcut_manager, "ui.font_scale_increase_keypad",
178 {ImGuiMod_Ctrl, ImGuiKey_KeypadAdd},
179 [editor_manager]() {
180 AdjustUiFontScaleBy(editor_manager, kUiFontScaleStep);
181 },
183
184 RegisterIfValid(
185 shortcut_manager, "ui.font_scale_decrease",
186 {ImGuiMod_Ctrl, ImGuiKey_Minus},
187 [editor_manager]() {
188 AdjustUiFontScaleBy(editor_manager, -kUiFontScaleStep);
189 },
191
192 RegisterIfValid(
193 shortcut_manager, "ui.font_scale_decrease_keypad",
194 {ImGuiMod_Ctrl, ImGuiKey_KeypadSubtract},
195 [editor_manager]() {
196 AdjustUiFontScaleBy(editor_manager, -kUiFontScaleStep);
197 },
199
200 RegisterIfValid(
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
210 RegisterIfValid(
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
226 RegisterIfValid(
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
240 RegisterIfValid(
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
249 RegisterIfValid(
250 shortcut_manager, "Quit", {ImGuiMod_Ctrl, ImGuiKey_Q},
251 [editor_manager]() {
252 if (editor_manager) {
253 editor_manager->Quit();
254 }
255 },
257
258 RegisterIfValid(
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
267 RegisterIfValid(
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
276 RegisterIfValid(
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
285 RegisterIfValid(
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
294 RegisterIfValid(
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
303 RegisterIfValid(
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
312 RegisterIfValid(
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
322 RegisterIfValid(
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
332 RegisterIfValid(
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
342 RegisterIfValid(
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) {
398 RegisterIfValid(
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) {
433 RegisterIfValid(
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* obj_selector = dungeon_editor->object_editor_panel();
449 auto* obj_editor = dungeon_editor->object_editor_content();
450 if (!obj_selector || !obj_editor)
451 return;
452
453 if (id == "dungeon.object.select_tool") {
454 // Unified mode: cancel placement to switch to selection
455 obj_selector->CancelPlacement();
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 // Unified mode: delete selected objects
461 obj_editor->DeleteSelectedObjects();
462 } else if (id == "dungeon.object.next_object") {
463 obj_editor->CycleObjectSelection(1);
464 } else if (id == "dungeon.object.prev_object") {
465 obj_editor->CycleObjectSelection(-1);
466 } else if (id == "dungeon.object.copy") {
467 obj_editor->CopySelectedObjects();
468 } else if (id == "dungeon.object.paste") {
469 obj_editor->PasteObjects();
470 } else if (id == "dungeon.object.delete") {
471 obj_editor->DeleteSelectedObjects();
472 }
473 },
475 }
476 }
477
478 // Editor-scoped Overworld shortcuts (basic tools)
479 if (editor_manager) {
480 for (const auto& def : kOverworldShortcuts) {
482 shortcut_manager, def.id, def.keys,
483 [editor_manager, id = def.id]() {
484 if (!editor_manager)
485 return;
486 auto* current_editor = editor_manager->GetCurrentEditor();
487 if (!current_editor ||
488 current_editor->type() != EditorType::kOverworld) {
489 return;
490 }
491 auto* editor_set = editor_manager->GetCurrentEditorSet();
492 auto* overworld_editor =
493 editor_set ? editor_set->GetOverworldEditor() : nullptr;
494 if (!overworld_editor)
495 return;
496
497 if (id == "overworld.brush_toggle") {
498 overworld_editor->ToggleBrushTool();
499 } else if (id == "overworld.fill") {
500 overworld_editor->ActivateFillTool();
501 } else if (id == "overworld.next_tile") {
502 overworld_editor->CycleTileSelection(1);
503 } else if (id == "overworld.prev_tile") {
504 overworld_editor->CycleTileSelection(-1);
505 }
506 },
507 Shortcut::Scope::kEditor);
508 }
509 }
510
511 // Editor-scoped Graphics shortcuts (sheet navigation)
512 if (editor_manager) {
513 for (const auto& def : kGraphicsShortcuts) {
515 shortcut_manager, def.id, def.keys,
516 [editor_manager, id = def.id]() {
517 if (!editor_manager)
518 return;
519 auto* current_editor = editor_manager->GetCurrentEditor();
520 if (!current_editor ||
521 current_editor->type() != EditorType::kGraphics) {
522 return;
523 }
524 auto* editor_set = editor_manager->GetCurrentEditorSet();
525 auto* graphics_editor =
526 editor_set ? editor_set->GetGraphicsEditor() : nullptr;
527 if (!graphics_editor)
528 return;
529
530 if (id == "graphics.next_sheet") {
531 graphics_editor->NextSheet();
532 } else if (id == "graphics.prev_sheet") {
533 graphics_editor->PrevSheet();
534 }
535 },
536 Shortcut::Scope::kEditor);
537 }
538 }
539
541 shortcut_manager, "Editor Selection", {ImGuiMod_Ctrl, ImGuiKey_E},
542 [ui_coordinator]() {
543 if (ui_coordinator) {
544 ui_coordinator->ShowEditorSelection();
545 }
546 },
547 Shortcut::Scope::kGlobal);
548
550 shortcut_manager, "Panel Browser",
551 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_B},
552 [ui_coordinator]() {
553 if (ui_coordinator) {
554 ui_coordinator->ShowWindowBrowser();
555 }
556 },
557 Shortcut::Scope::kGlobal);
559 shortcut_manager, "Window Browser",
560 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_B},
561 [ui_coordinator]() {
562 if (ui_coordinator) {
563 ui_coordinator->ShowWindowBrowser();
564 }
565 },
566 Shortcut::Scope::kGlobal);
568 shortcut_manager, "Panel Browser (Alt)",
569 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_P},
570 [ui_coordinator]() {
571 if (ui_coordinator) {
572 ui_coordinator->ShowWindowBrowser();
573 }
574 },
575 Shortcut::Scope::kGlobal);
577 shortcut_manager, "Window Browser (Alt)",
578 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_P},
579 [ui_coordinator]() {
580 if (ui_coordinator) {
581 ui_coordinator->ShowWindowBrowser();
582 }
583 },
584 Shortcut::Scope::kGlobal);
585
587 shortcut_manager, "View: Previous Right Panel",
588 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_LeftBracket},
589 [editor_manager]() {
590 if (!editor_manager) {
591 return;
592 }
593 if (auto* right_panel = editor_manager->right_drawer_manager()) {
594 right_panel->CycleToPreviousDrawer();
595 }
596 },
597 Shortcut::Scope::kGlobal);
599 shortcut_manager, "View: Previous Right Drawer",
600 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_LeftBracket},
601 [editor_manager]() {
602 if (!editor_manager) {
603 return;
604 }
605 if (auto* right_drawer = editor_manager->right_drawer_manager()) {
606 right_drawer->CycleToPreviousDrawer();
607 }
608 },
609 Shortcut::Scope::kGlobal);
610
612 shortcut_manager, "View: Next Right Panel",
613 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_RightBracket},
614 [editor_manager]() {
615 if (!editor_manager) {
616 return;
617 }
618 if (auto* right_panel = editor_manager->right_drawer_manager()) {
619 right_panel->CycleToNextDrawer();
620 }
621 },
622 Shortcut::Scope::kGlobal);
624 shortcut_manager, "View: Next Right Drawer",
625 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_RightBracket},
626 [editor_manager]() {
627 if (!editor_manager) {
628 return;
629 }
630 if (auto* right_drawer = editor_manager->right_drawer_manager()) {
631 right_drawer->CycleToNextDrawer();
632 }
633 },
634 Shortcut::Scope::kGlobal);
635
636 if (window_manager) {
637 // Note: Using Ctrl+Alt for panel shortcuts to avoid conflicts with Save As
638 // (Ctrl+Shift+S)
640 shortcut_manager, "Show Dungeon Panels",
641 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_D},
642 [window_manager]() {
643 window_manager->ShowAllWindowsInCategory(0, "Dungeon");
644 },
645 Shortcut::Scope::kEditor);
647 shortcut_manager, "Show Dungeon Windows",
648 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_D},
649 [window_manager]() {
650 window_manager->ShowAllWindowsInCategory(0, "Dungeon");
651 },
652 Shortcut::Scope::kEditor);
654 shortcut_manager, "Show Graphics Panels",
655 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_G},
656 [window_manager]() {
657 window_manager->ShowAllWindowsInCategory(0, "Graphics");
658 },
659 Shortcut::Scope::kEditor);
661 shortcut_manager, "Show Graphics Windows",
662 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_G},
663 [window_manager]() {
664 window_manager->ShowAllWindowsInCategory(0, "Graphics");
665 },
666 Shortcut::Scope::kEditor);
668 shortcut_manager, "Show Screen Panels",
669 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_S},
670 [window_manager]() {
671 window_manager->ShowAllWindowsInCategory(0, "Screen");
672 },
673 Shortcut::Scope::kEditor);
675 shortcut_manager, "Show Screen Windows",
676 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_S},
677 [window_manager]() {
678 window_manager->ShowAllWindowsInCategory(0, "Screen");
679 },
680 Shortcut::Scope::kEditor);
681 }
682
683#ifdef YAZE_BUILD_AGENT_UI
684 RegisterIfValid(shortcut_manager, "Agent Editor",
685 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_A},
686 [editor_manager]() {
687 if (editor_manager) {
688 editor_manager->ShowAIAgent();
689 }
690 });
691
692 RegisterIfValid(shortcut_manager, "Agent Sidebar",
693 {ImGuiMod_Ctrl, ImGuiKey_H}, [editor_manager]() {
694 if (editor_manager) {
695 editor_manager->ShowChatHistory();
696 }
697 });
698
699 RegisterIfValid(shortcut_manager, "Proposal Drawer",
700 {ImGuiMod_Ctrl, ImGuiMod_Shift,
701 ImGuiKey_R}, // Changed from Ctrl+P to Ctrl+Shift+R
702 [editor_manager]() {
703 if (editor_manager) {
704 editor_manager->ShowProposalDrawer();
705 }
706 });
707#endif
708
709 // ============================================================================
710 // Layout Presets and Profiles (command palette only - no keyboard shortcuts)
711 // ============================================================================
712 shortcut_manager->RegisterCommand("Layout Profile: Code", [editor_manager]() {
713 if (editor_manager) {
714 editor_manager->ApplyLayoutProfile("code");
715 }
716 });
717 shortcut_manager->RegisterCommand(
718 "Layout Profile: Debug", [editor_manager]() {
719 if (editor_manager) {
720 editor_manager->ApplyLayoutProfile("debug");
721 }
722 });
723 shortcut_manager->RegisterCommand(
724 "Layout Profile: Mapping", [editor_manager]() {
725 if (editor_manager) {
726 editor_manager->ApplyLayoutProfile("mapping");
727 }
728 });
729 shortcut_manager->RegisterCommand("Layout Profile: Chat", [editor_manager]() {
730 if (editor_manager) {
731 editor_manager->ApplyLayoutProfile("chat");
732 }
733 });
734 shortcut_manager->RegisterCommand(
735 "Layout Snapshot: Capture", [editor_manager]() {
736 if (editor_manager) {
737 editor_manager->CaptureTemporaryLayoutSnapshot();
738 }
739 });
740 shortcut_manager->RegisterCommand(
741 "Layout Snapshot: Restore", [editor_manager]() {
742 if (editor_manager) {
743 editor_manager->RestoreTemporaryLayoutSnapshot();
744 }
745 });
746 shortcut_manager->RegisterCommand(
747 "Layout Snapshot: Clear", [editor_manager]() {
748 if (editor_manager) {
749 editor_manager->ClearTemporaryLayoutSnapshot();
750 }
751 });
752
753 shortcut_manager->RegisterCommand(
754 "Layout: Apply Minimal Preset", [editor_manager]() {
755 if (editor_manager) {
756 editor_manager->ApplyLayoutPreset("Minimal");
757 }
758 });
759 shortcut_manager->RegisterCommand(
760 "Layout: Apply Developer Preset", [editor_manager]() {
761 if (editor_manager) {
762 editor_manager->ApplyLayoutPreset("Developer");
763 }
764 });
765 shortcut_manager->RegisterCommand(
766 "Layout: Apply Designer Preset", [editor_manager]() {
767 if (editor_manager) {
768 editor_manager->ApplyLayoutPreset("Designer");
769 }
770 });
771 shortcut_manager->RegisterCommand(
772 "Layout: Apply Modder Preset", [editor_manager]() {
773 if (editor_manager) {
774 editor_manager->ApplyLayoutPreset("Modder");
775 }
776 });
777 shortcut_manager->RegisterCommand(
778 "Layout: Apply Overworld Expert Preset", [editor_manager]() {
779 if (editor_manager) {
780 editor_manager->ApplyLayoutPreset("Overworld Expert");
781 }
782 });
783 shortcut_manager->RegisterCommand(
784 "Layout: Apply Dungeon Expert Preset", [editor_manager]() {
785 if (editor_manager) {
786 editor_manager->ApplyLayoutPreset("Dungeon Expert");
787 }
788 });
789 shortcut_manager->RegisterCommand(
790 "Layout: Apply Testing Preset", [editor_manager]() {
791 if (editor_manager) {
792 editor_manager->ApplyLayoutPreset("Testing");
793 }
794 });
795 shortcut_manager->RegisterCommand(
796 "Layout: Apply Audio Preset", [editor_manager]() {
797 if (editor_manager) {
798 editor_manager->ApplyLayoutPreset("Audio");
799 }
800 });
801 shortcut_manager->RegisterCommand(
802 "Layout: Reset Current Editor", [editor_manager]() {
803 if (editor_manager) {
804 editor_manager->ResetCurrentEditorLayout();
805 }
806 });
807
808 // ============================================================================
809 // Right Drawer / Panel Toggle Commands (command palette only)
810 // ============================================================================
811 if (editor_manager) {
812 using DrawerType = RightDrawerManager::DrawerType;
813 auto* right_drawer_manager = editor_manager->right_drawer_manager();
814 if (right_drawer_manager) {
815 struct DrawerCmd {
816 const char* label;
817 DrawerType type;
818 };
819 DrawerCmd drawer_cmds[] = {
820 {"View: Toggle AI Agent Panel", DrawerType::kAgentChat},
821 {"View: Toggle AI Agent Drawer", DrawerType::kAgentChat},
822 {"View: Toggle Proposals Panel", DrawerType::kProposals},
823 {"View: Toggle Proposals Drawer", DrawerType::kProposals},
824 {"View: Toggle Settings Panel", DrawerType::kSettings},
825 {"View: Toggle Settings Drawer", DrawerType::kSettings},
826 {"View: Toggle Help Panel", DrawerType::kHelp},
827 {"View: Toggle Help Drawer", DrawerType::kHelp},
828 {"View: Toggle Notifications", DrawerType::kNotifications},
829 {"View: Toggle Notifications Drawer", DrawerType::kNotifications},
830 {"View: Toggle Properties Panel", DrawerType::kProperties},
831 {"View: Toggle Properties Drawer", DrawerType::kProperties},
832 {"View: Toggle Project Panel", DrawerType::kProject},
833 {"View: Toggle Project Drawer", DrawerType::kProject},
834 };
835 for (const auto& cmd : drawer_cmds) {
836 shortcut_manager->RegisterCommand(
837 cmd.label, [right_drawer_manager, drawer_type = cmd.type]() {
838 right_drawer_manager->ToggleDrawer(drawer_type);
839 });
840 }
841 shortcut_manager->RegisterCommand(
842 "View: Previous Right Panel", [right_drawer_manager]() {
843 right_drawer_manager->CycleToPreviousDrawer();
844 });
845 shortcut_manager->RegisterCommand(
846 "View: Previous Right Drawer", [right_drawer_manager]() {
847 right_drawer_manager->CycleToPreviousDrawer();
848 });
849 shortcut_manager->RegisterCommand(
850 "View: Next Right Panel", [right_drawer_manager]() {
851 right_drawer_manager->CycleToNextDrawer();
852 });
853 shortcut_manager->RegisterCommand(
854 "View: Next Right Drawer", [right_drawer_manager]() {
855 right_drawer_manager->CycleToNextDrawer();
856 });
857 }
858 }
859
860 // ============================================================================
861 // Window + Panel Visibility Commands (command palette only)
862 // ============================================================================
863 if (window_manager) {
864 auto categories = window_manager->GetAllCategories();
865 int session_id = 0; // Default session for command registration
866
867 shortcut_manager->RegisterCommand(
868 "View: Show Panel Browser",
869 [window_manager]() { window_manager->TriggerShowWindowBrowser(); });
870 shortcut_manager->RegisterCommand(
871 "View: Show Window Browser",
872 [window_manager]() { window_manager->TriggerShowWindowBrowser(); });
873
874 for (const auto& category : categories) {
875 auto windows = window_manager->GetWindowsInCategory(session_id, category);
876 for (const auto& window : windows) {
877 const std::string window_id = window.card_id;
878 const std::string display_name = window.display_name;
879
880 shortcut_manager->RegisterCommand(
881 absl::StrFormat("View: Show %s", display_name),
882 [window_manager, window_id]() {
883 if (window_manager) {
884 window_manager->OpenWindow(0, window_id);
885 }
886 });
887 shortcut_manager->RegisterCommand(
888 absl::StrFormat("View: Hide %s", display_name),
889 [window_manager, window_id]() {
890 if (window_manager) {
891 window_manager->CloseWindow(0, window_id);
892 }
893 });
894 shortcut_manager->RegisterCommand(
895 absl::StrFormat("View: Toggle %s", display_name),
896 [window_manager, window_id]() {
897 if (window_manager) {
898 window_manager->ToggleWindow(0, window_id);
899 }
900 });
901
902 shortcut_manager->RegisterCommand(
903 absl::StrFormat("View: Open %s Window", display_name),
904 [window_manager, window_id]() {
905 if (window_manager) {
906 window_manager->OpenWindow(0, window_id);
907 }
908 });
909 shortcut_manager->RegisterCommand(
910 absl::StrFormat("View: Close %s Window", display_name),
911 [window_manager, window_id]() {
912 if (window_manager) {
913 window_manager->CloseWindow(0, window_id);
914 }
915 });
916 shortcut_manager->RegisterCommand(
917 absl::StrFormat("View: Toggle %s Window", display_name),
918 [window_manager, window_id]() {
919 if (window_manager) {
920 window_manager->ToggleWindow(0, window_id);
921 }
922 });
923 }
924
925 shortcut_manager->RegisterCommand(
926 absl::StrFormat("View: Show All %s Panels", category),
927 [window_manager, category]() {
928 if (window_manager) {
929 window_manager->ShowAllWindowsInCategory(0, category);
930 }
931 });
932 shortcut_manager->RegisterCommand(
933 absl::StrFormat("View: Hide All %s Panels", category),
934 [window_manager, category]() {
935 if (window_manager) {
936 window_manager->HideAllWindowsInCategory(0, category);
937 }
938 });
939 shortcut_manager->RegisterCommand(
940 absl::StrFormat("View: Show All %s Windows", category),
941 [window_manager, category]() {
942 if (window_manager) {
943 window_manager->ShowAllWindowsInCategory(0, category);
944 }
945 });
946 shortcut_manager->RegisterCommand(
947 absl::StrFormat("View: Hide All %s Windows", category),
948 [window_manager, category]() {
949 if (window_manager) {
950 window_manager->HideAllWindowsInCategory(0, category);
951 }
952 });
953 }
954 }
955}
956
958 ShortcutManager* shortcut_manager) {
959 if (!shortcut_manager) {
960 return;
961 }
962
963 auto* menu_orchestrator = deps.menu_orchestrator;
964 auto* session_coordinator = deps.session_coordinator;
965 auto* workspace_manager = deps.workspace_manager;
966
967 RegisterIfValid(shortcut_manager, "New Session",
968 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_N},
969 [session_coordinator]() {
970 if (session_coordinator) {
971 session_coordinator->CreateNewSession();
972 }
973 });
974
975 RegisterIfValid(shortcut_manager, "Duplicate Session",
976 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_D},
977 [session_coordinator]() {
978 if (session_coordinator) {
979 session_coordinator->DuplicateCurrentSession();
980 }
981 });
982
983 RegisterIfValid(shortcut_manager, "Close Session",
984 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_W},
985 [session_coordinator]() {
986 if (session_coordinator) {
987 session_coordinator->CloseCurrentSession();
988 }
989 });
990
991 RegisterIfValid(shortcut_manager, "Session Switcher",
992 {ImGuiMod_Ctrl, ImGuiKey_Tab}, [session_coordinator]() {
993 if (session_coordinator) {
994 session_coordinator->ShowSessionSwitcher();
995 }
996 });
997
998 RegisterIfValid(shortcut_manager, "Save Layout",
999 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_L},
1000 [workspace_manager]() {
1001 if (workspace_manager) {
1002 workspace_manager->SaveWorkspaceLayout();
1003 }
1004 });
1005
1006 RegisterIfValid(shortcut_manager, "Load Layout",
1007 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_O},
1008 [workspace_manager]() {
1009 if (workspace_manager) {
1010 workspace_manager->LoadWorkspaceLayout();
1011 }
1012 });
1013
1014 // Note: Changed from Ctrl+Shift+R to Ctrl+Alt+R to avoid conflict with
1015 // Proposal Drawer
1016 RegisterIfValid(shortcut_manager, "Reset Layout",
1017 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_R},
1018 [workspace_manager]() {
1019 if (workspace_manager) {
1020 workspace_manager->ResetWorkspaceLayout();
1021 }
1022 });
1023
1024 RegisterIfValid(shortcut_manager, "Maximize Window", ImGuiKey_F11,
1025 [workspace_manager]() {
1026 if (workspace_manager) {
1027 workspace_manager->MaximizeCurrentWindow();
1028 }
1029 });
1030
1031#ifdef YAZE_ENABLE_TESTING
1032 RegisterIfValid(shortcut_manager, "Test Dashboard",
1033 {ImGuiMod_Ctrl, ImGuiKey_T}, [menu_orchestrator]() {
1034 if (menu_orchestrator) {
1035 menu_orchestrator->OnShowTestDashboard();
1036 }
1037 });
1038#endif
1039}
1040
1042 ShortcutManager* shortcut_manager) {
1043 if (!shortcut_manager || !deps.window_manager) {
1044 return;
1045 }
1046
1047 auto* window_manager = deps.window_manager;
1048 auto* user_settings = deps.user_settings;
1049 int session_id = deps.session_coordinator
1051 : 0;
1052
1053 // Get all categories and panels
1054 auto categories = window_manager->GetAllCategories();
1055
1056 for (const auto& category : categories) {
1057 auto panels = window_manager->GetWindowsInCategory(session_id, category);
1058
1059 for (const auto& panel : panels) {
1060 std::string shortcut_string;
1061
1062 // Check for user-defined shortcut first
1063 if (user_settings) {
1064 auto it = user_settings->prefs().panel_shortcuts.find(panel.card_id);
1065 if (it != user_settings->prefs().panel_shortcuts.end()) {
1066 shortcut_string = it->second;
1067 }
1068 }
1069
1070 // Fall back to default shortcut_hint
1071 if (shortcut_string.empty() && !panel.shortcut_hint.empty()) {
1072 shortcut_string = panel.shortcut_hint;
1073 }
1074
1075 // If we have a shortcut, parse and register it
1076 if (!shortcut_string.empty()) {
1077 auto keys = ParseShortcut(shortcut_string);
1078 if (!keys.empty()) {
1079 std::string panel_id_copy = panel.card_id;
1080 // Toggle panel visibility shortcut
1081 if (panel.shortcut_scope == WindowDescriptor::ShortcutScope::kPanel) {
1082 std::string toggle_id = "view.toggle." + panel.card_id;
1083 RegisterIfValid(shortcut_manager, toggle_id, keys,
1084 [window_manager, panel_id_copy, session_id]() {
1085 window_manager->ToggleWindow(session_id,
1086 panel_id_copy);
1087 });
1088 }
1089 }
1090 }
1091 }
1092 }
1093}
1094
1095} // namespace yaze::editor
The EditorManager controls the main editor window and manages the various editor classes.
void SetFontGlobalScale(float scale)
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)
void RegisterShortcut(const std::string &name, const std::vector< ImGuiKey > &keys, Shortcut::Scope scope=Shortcut::Scope::kGlobal)
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)