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 && editor_manager->popup_manager()) {
230 editor_manager->popup_manager()->Show(PopupID::kSaveAs);
231 }
232 },
234
235 RegisterIfValid(
236 shortcut_manager, "Close ROM", {ImGuiMod_Ctrl, ImGuiKey_W},
237 [editor_manager]() {
238 if (editor_manager) {
239 editor_manager->CloseCurrentSession();
240 }
241 },
243
244 RegisterIfValid(
245 shortcut_manager, "Quit", {ImGuiMod_Ctrl, ImGuiKey_Q},
246 [editor_manager]() {
247 if (editor_manager) {
248 editor_manager->Quit();
249 }
250 },
252
253 RegisterIfValid(
254 shortcut_manager, "Undo", {ImGuiMod_Ctrl, ImGuiKey_Z},
255 [editor_manager]() {
256 if (editor_manager && editor_manager->GetCurrentEditor()) {
257 editor_manager->GetCurrentEditor()->Undo();
258 }
259 },
261
262 RegisterIfValid(
263 shortcut_manager, "Redo", {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_Z},
264 [editor_manager]() {
265 if (editor_manager && editor_manager->GetCurrentEditor()) {
266 editor_manager->GetCurrentEditor()->Redo();
267 }
268 },
270
271 RegisterIfValid(
272 shortcut_manager, "Cut", {ImGuiMod_Ctrl, ImGuiKey_X},
273 [editor_manager]() {
274 if (editor_manager && editor_manager->GetCurrentEditor()) {
275 editor_manager->GetCurrentEditor()->Cut();
276 }
277 },
279
280 RegisterIfValid(
281 shortcut_manager, "Copy", {ImGuiMod_Ctrl, ImGuiKey_C},
282 [editor_manager]() {
283 if (editor_manager && editor_manager->GetCurrentEditor()) {
284 editor_manager->GetCurrentEditor()->Copy();
285 }
286 },
288
289 RegisterIfValid(
290 shortcut_manager, "Paste", {ImGuiMod_Ctrl, ImGuiKey_V},
291 [editor_manager]() {
292 if (editor_manager && editor_manager->GetCurrentEditor()) {
293 editor_manager->GetCurrentEditor()->Paste();
294 }
295 },
297
298 RegisterIfValid(
299 shortcut_manager, "Find", {ImGuiMod_Ctrl, ImGuiKey_F},
300 [editor_manager]() {
301 if (editor_manager && editor_manager->GetCurrentEditor()) {
302 editor_manager->GetCurrentEditor()->Find();
303 }
304 },
306
307 RegisterIfValid(
308 shortcut_manager, "Command Palette",
309 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_P},
310 [ui_coordinator]() {
311 if (ui_coordinator) {
312 ui_coordinator->ShowCommandPalette();
313 }
314 },
316
317 RegisterIfValid(
318 shortcut_manager, "Window Finder", {ImGuiMod_Ctrl, ImGuiKey_P},
319 [ui_coordinator]() {
320 if (ui_coordinator) {
321 ui_coordinator->ShowPanelFinder();
322 }
323 },
325
326 RegisterIfValid(
327 shortcut_manager, "Keyboard Shortcuts",
328 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_Slash},
329 [ui_coordinator]() {
330 if (ui_coordinator) {
331 ui_coordinator->ShowShortcutsBrowser();
332 }
333 },
335
336 RegisterIfValid(
337 shortcut_manager, "Global Search",
338 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_K},
339 [ui_coordinator]() {
340 if (ui_coordinator) {
341 ui_coordinator->ShowGlobalSearch();
342 }
343 },
345
346 RegisterIfValid(
347 shortcut_manager, "Load Last ROM", {ImGuiMod_Ctrl, ImGuiKey_R},
348 [editor_manager]() {
350 if (!recent.GetRecentFiles().empty() && editor_manager) {
351 editor_manager->OpenRomOrProject(recent.GetRecentFiles().front());
352 }
353 },
355
356 RegisterIfValid(
357 shortcut_manager, "Show About", ImGuiKey_F1,
358 [popup_manager]() {
359 if (popup_manager) {
360 popup_manager->Show("About");
361 }
362 },
364
365 auto register_editor_shortcut = [&](EditorType type, ImGuiKey key) {
366 RegisterIfValid(shortcut_manager,
367 absl::StrFormat("switch.%d", static_cast<int>(type)),
368 {ImGuiMod_Ctrl, key}, [editor_manager, type]() {
369 if (editor_manager) {
370 editor_manager->SwitchToEditor(type);
371 }
372 });
373 };
374
375 register_editor_shortcut(EditorType::kOverworld, ImGuiKey_1);
376 register_editor_shortcut(EditorType::kDungeon, ImGuiKey_2);
377 register_editor_shortcut(EditorType::kGraphics, ImGuiKey_3);
378 register_editor_shortcut(EditorType::kSprite, ImGuiKey_4);
379 register_editor_shortcut(EditorType::kMessage, ImGuiKey_5);
380 register_editor_shortcut(EditorType::kMusic, ImGuiKey_6);
381 register_editor_shortcut(EditorType::kPalette, ImGuiKey_7);
382 register_editor_shortcut(EditorType::kScreen, ImGuiKey_8);
383 register_editor_shortcut(EditorType::kAssembly, ImGuiKey_9);
384 register_editor_shortcut(EditorType::kSettings, ImGuiKey_0);
385
386 // ============================================================================
387 // Editor Switch Commands (command palette with friendly names)
388 // ============================================================================
389 auto register_editor_command = [&](EditorType type, const std::string& name) {
390 shortcut_manager->RegisterCommand(
391 absl::StrFormat("Switch to %s Editor", name), [editor_manager, type]() {
392 if (editor_manager) {
393 editor_manager->SwitchToEditor(type);
394 }
395 });
396 };
397
398 register_editor_command(EditorType::kOverworld, "Overworld");
399 register_editor_command(EditorType::kDungeon, "Dungeon");
400 register_editor_command(EditorType::kGraphics, "Graphics");
401 register_editor_command(EditorType::kSprite, "Sprite");
402 register_editor_command(EditorType::kMessage, "Message");
403 register_editor_command(EditorType::kMusic, "Music");
404 register_editor_command(EditorType::kPalette, "Palette");
405 register_editor_command(EditorType::kScreen, "Screen");
406 register_editor_command(EditorType::kAssembly, "Assembly");
407 register_editor_command(EditorType::kSettings, "Settings");
408
409 // Editor-scoped Music shortcuts (toggle playback, speed controls)
410 if (editor_manager) {
411 for (const auto& def : kMusicEditorShortcuts) {
412 RegisterIfValid(
413 shortcut_manager, def.id, def.keys,
414 [editor_manager, id = def.id]() {
415 if (!editor_manager)
416 return;
417 auto* current_editor = editor_manager->GetCurrentEditor();
418 if (!current_editor ||
419 current_editor->type() != EditorType::kMusic) {
420 return;
421 }
422 auto* editor_set = editor_manager->GetCurrentEditorSet();
423 auto* music_editor =
424 editor_set ? editor_set->GetMusicEditor() : nullptr;
425 if (!music_editor)
426 return;
427
428 if (id == "music.play_pause") {
429 music_editor->TogglePlayPause();
430 } else if (id == "music.stop") {
431 music_editor->StopPlayback();
432 } else if (id == "music.speed_up" ||
433 id == "music.speed_up_keypad") {
434 music_editor->SpeedUp();
435 } else if (id == "music.speed_down" ||
436 id == "music.speed_down_keypad") {
437 music_editor->SlowDown();
438 }
439 },
441 }
442 }
443
444 // Editor-scoped Dungeon shortcuts (object tools)
445 if (editor_manager) {
446 for (const auto& def : kDungeonEditorShortcuts) {
447 RegisterIfValid(
448 shortcut_manager, def.id, def.keys,
449 [editor_manager, id = def.id]() {
450 if (!editor_manager)
451 return;
452 auto* current_editor = editor_manager->GetCurrentEditor();
453 if (!current_editor ||
454 current_editor->type() != EditorType::kDungeon) {
455 return;
456 }
457 auto* editor_set = editor_manager->GetCurrentEditorSet();
458 auto* dungeon_editor =
459 editor_set ? editor_set->GetDungeonEditor() : nullptr;
460 if (!dungeon_editor)
461 return;
462 auto* obj_selector = dungeon_editor->object_editor_panel();
463 auto* obj_editor = dungeon_editor->object_editor_content();
464 if (!obj_selector || !obj_editor)
465 return;
466
467 if (id == "dungeon.object.select_tool") {
468 // Unified mode: cancel placement to switch to selection
469 obj_selector->CancelPlacement();
470 } else if (id == "dungeon.object.place_tool") {
471 // Unified mode: handled by object selector click
472 // No-op (mode is controlled by selecting an object)
473 } else if (id == "dungeon.object.delete_tool") {
474 dungeon_editor->QueueRoomCanvasDeleteShortcut();
475 } else if (id == "dungeon.object.next_object") {
476 obj_editor->CycleObjectSelection(1);
477 } else if (id == "dungeon.object.prev_object") {
478 obj_editor->CycleObjectSelection(-1);
479 } else if (id == "dungeon.object.copy") {
480 obj_editor->CopySelectedObjects();
481 } else if (id == "dungeon.object.paste") {
482 obj_editor->PasteObjects();
483 } else if (id == "dungeon.object.delete") {
484 dungeon_editor->QueueRoomCanvasDeleteShortcut();
485 }
486 },
488 }
489 }
490
491 // Editor-scoped Overworld shortcuts (basic tools)
492 if (editor_manager) {
493 for (const auto& def : kOverworldShortcuts) {
495 shortcut_manager, def.id, def.keys,
496 [editor_manager, id = def.id]() {
497 if (!editor_manager)
498 return;
499 auto* current_editor = editor_manager->GetCurrentEditor();
500 if (!current_editor ||
501 current_editor->type() != EditorType::kOverworld) {
502 return;
503 }
504 auto* editor_set = editor_manager->GetCurrentEditorSet();
505 auto* overworld_editor =
506 editor_set ? editor_set->GetOverworldEditor() : nullptr;
507 if (!overworld_editor)
508 return;
509
510 if (id == "overworld.brush_toggle") {
511 overworld_editor->ToggleBrushTool();
512 } else if (id == "overworld.fill") {
513 overworld_editor->ActivateFillTool();
514 } else if (id == "overworld.next_tile") {
515 overworld_editor->CycleTileSelection(1);
516 } else if (id == "overworld.prev_tile") {
517 overworld_editor->CycleTileSelection(-1);
518 }
519 },
520 Shortcut::Scope::kEditor);
521 }
522 }
523
524 // Editor-scoped Graphics shortcuts (sheet navigation)
525 if (editor_manager) {
526 for (const auto& def : kGraphicsShortcuts) {
528 shortcut_manager, def.id, def.keys,
529 [editor_manager, id = def.id]() {
530 if (!editor_manager)
531 return;
532 auto* current_editor = editor_manager->GetCurrentEditor();
533 if (!current_editor ||
534 current_editor->type() != EditorType::kGraphics) {
535 return;
536 }
537 auto* editor_set = editor_manager->GetCurrentEditorSet();
538 auto* graphics_editor =
539 editor_set ? editor_set->GetGraphicsEditor() : nullptr;
540 if (!graphics_editor)
541 return;
542
543 if (id == "graphics.next_sheet") {
544 graphics_editor->NextSheet();
545 } else if (id == "graphics.prev_sheet") {
546 graphics_editor->PrevSheet();
547 }
548 },
549 Shortcut::Scope::kEditor);
550 }
551 }
552
554 shortcut_manager, "Editor Selection", {ImGuiMod_Ctrl, ImGuiKey_E},
555 [ui_coordinator]() {
556 if (ui_coordinator) {
557 ui_coordinator->ShowEditorSelection();
558 }
559 },
560 Shortcut::Scope::kGlobal);
561
563 shortcut_manager, "Panel Browser",
564 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_B},
565 [ui_coordinator]() {
566 if (ui_coordinator) {
567 ui_coordinator->ShowWindowBrowser();
568 }
569 },
570 Shortcut::Scope::kGlobal);
572 shortcut_manager, "Window Browser",
573 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_B},
574 [ui_coordinator]() {
575 if (ui_coordinator) {
576 ui_coordinator->ShowWindowBrowser();
577 }
578 },
579 Shortcut::Scope::kGlobal);
581 shortcut_manager, "Panel Browser (Alt)",
582 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_P},
583 [ui_coordinator]() {
584 if (ui_coordinator) {
585 ui_coordinator->ShowWindowBrowser();
586 }
587 },
588 Shortcut::Scope::kGlobal);
590 shortcut_manager, "Window Browser (Alt)",
591 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_P},
592 [ui_coordinator]() {
593 if (ui_coordinator) {
594 ui_coordinator->ShowWindowBrowser();
595 }
596 },
597 Shortcut::Scope::kGlobal);
598
600 shortcut_manager, "View: Previous Right Panel",
601 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_LeftBracket},
602 [editor_manager]() {
603 if (!editor_manager) {
604 return;
605 }
606 if (auto* right_panel = editor_manager->right_drawer_manager()) {
607 right_panel->CycleToPreviousDrawer();
608 }
609 },
610 Shortcut::Scope::kGlobal);
612 shortcut_manager, "View: Previous Right Drawer",
613 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_LeftBracket},
614 [editor_manager]() {
615 if (!editor_manager) {
616 return;
617 }
618 if (auto* right_drawer = editor_manager->right_drawer_manager()) {
619 right_drawer->CycleToPreviousDrawer();
620 }
621 },
622 Shortcut::Scope::kGlobal);
623
625 shortcut_manager, "View: Next Right Panel",
626 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_RightBracket},
627 [editor_manager]() {
628 if (!editor_manager) {
629 return;
630 }
631 if (auto* right_panel = editor_manager->right_drawer_manager()) {
632 right_panel->CycleToNextDrawer();
633 }
634 },
635 Shortcut::Scope::kGlobal);
637 shortcut_manager, "View: Next Right Drawer",
638 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_RightBracket},
639 [editor_manager]() {
640 if (!editor_manager) {
641 return;
642 }
643 if (auto* right_drawer = editor_manager->right_drawer_manager()) {
644 right_drawer->CycleToNextDrawer();
645 }
646 },
647 Shortcut::Scope::kGlobal);
648
649 if (window_manager) {
650 // Note: Using Ctrl+Alt for panel shortcuts to avoid conflicts with Save As
651 // (Ctrl+Shift+S)
653 shortcut_manager, "Show Dungeon Panels",
654 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_D},
655 [window_manager]() {
656 window_manager->ShowAllWindowsInCategory(
657 window_manager->GetActiveSessionId(), "Dungeon");
658 },
659 Shortcut::Scope::kEditor);
661 shortcut_manager, "Show Dungeon Windows",
662 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_D},
663 [window_manager]() {
664 window_manager->ShowAllWindowsInCategory(
665 window_manager->GetActiveSessionId(), "Dungeon");
666 },
667 Shortcut::Scope::kEditor);
669 shortcut_manager, "Show Graphics Panels",
670 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_G},
671 [window_manager]() {
672 window_manager->ShowAllWindowsInCategory(
673 window_manager->GetActiveSessionId(), "Graphics");
674 },
675 Shortcut::Scope::kEditor);
677 shortcut_manager, "Show Graphics Windows",
678 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_G},
679 [window_manager]() {
680 window_manager->ShowAllWindowsInCategory(
681 window_manager->GetActiveSessionId(), "Graphics");
682 },
683 Shortcut::Scope::kEditor);
685 shortcut_manager, "Show Screen Panels",
686 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_S},
687 [window_manager]() {
688 window_manager->ShowAllWindowsInCategory(
689 window_manager->GetActiveSessionId(), "Screen");
690 },
691 Shortcut::Scope::kEditor);
693 shortcut_manager, "Show Screen Windows",
694 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_S},
695 [window_manager]() {
696 window_manager->ShowAllWindowsInCategory(
697 window_manager->GetActiveSessionId(), "Screen");
698 },
699 Shortcut::Scope::kEditor);
700 }
701
702#ifdef YAZE_BUILD_AGENT_UI
703 RegisterIfValid(shortcut_manager, "Agent Editor",
704 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_A},
705 [editor_manager]() {
706 if (editor_manager) {
707 editor_manager->ShowAIAgent();
708 }
709 });
710
711 RegisterIfValid(shortcut_manager, "Agent Sidebar",
712 {ImGuiMod_Ctrl, ImGuiKey_H}, [editor_manager]() {
713 if (editor_manager) {
714 editor_manager->ShowChatHistory();
715 }
716 });
717
718 RegisterIfValid(shortcut_manager, "Proposal Drawer",
719 {ImGuiMod_Ctrl, ImGuiMod_Shift,
720 ImGuiKey_R}, // Changed from Ctrl+P to Ctrl+Shift+R
721 [editor_manager]() {
722 if (editor_manager) {
723 editor_manager->ShowProposalDrawer();
724 }
725 });
726#endif
727
728 // ============================================================================
729 // Layout Presets and Profiles (command palette only - no keyboard shortcuts)
730 // ============================================================================
731 shortcut_manager->RegisterCommand("Layout Profile: Code", [editor_manager]() {
732 if (editor_manager) {
733 editor_manager->ApplyLayoutProfile("code");
734 }
735 });
736 shortcut_manager->RegisterCommand(
737 "Layout Profile: Debug", [editor_manager]() {
738 if (editor_manager) {
739 editor_manager->ApplyLayoutProfile("debug");
740 }
741 });
742 shortcut_manager->RegisterCommand(
743 "Layout Profile: Mapping", [editor_manager]() {
744 if (editor_manager) {
745 editor_manager->ApplyLayoutProfile("mapping");
746 }
747 });
748 shortcut_manager->RegisterCommand("Layout Profile: Chat", [editor_manager]() {
749 if (editor_manager) {
750 editor_manager->ApplyLayoutProfile("chat");
751 }
752 });
753 shortcut_manager->RegisterCommand(
754 "Layout Snapshot: Capture", [editor_manager]() {
755 if (editor_manager) {
756 editor_manager->CaptureTemporaryLayoutSnapshot();
757 }
758 });
759 shortcut_manager->RegisterCommand(
760 "Layout Snapshot: Restore", [editor_manager]() {
761 if (editor_manager) {
762 editor_manager->RestoreTemporaryLayoutSnapshot();
763 }
764 });
765 shortcut_manager->RegisterCommand(
766 "Layout Snapshot: Clear", [editor_manager]() {
767 if (editor_manager) {
768 editor_manager->ClearTemporaryLayoutSnapshot();
769 }
770 });
771
772 shortcut_manager->RegisterCommand(
773 "Layout: Apply Minimal Preset", [editor_manager]() {
774 if (editor_manager) {
775 editor_manager->ApplyLayoutPreset("Minimal");
776 }
777 });
778 shortcut_manager->RegisterCommand(
779 "Layout: Apply Developer Preset", [editor_manager]() {
780 if (editor_manager) {
781 editor_manager->ApplyLayoutPreset("Developer");
782 }
783 });
784 shortcut_manager->RegisterCommand(
785 "Layout: Apply Designer Preset", [editor_manager]() {
786 if (editor_manager) {
787 editor_manager->ApplyLayoutPreset("Designer");
788 }
789 });
790 shortcut_manager->RegisterCommand(
791 "Layout: Apply Modder Preset", [editor_manager]() {
792 if (editor_manager) {
793 editor_manager->ApplyLayoutPreset("Modder");
794 }
795 });
796 shortcut_manager->RegisterCommand(
797 "Layout: Apply Overworld Expert Preset", [editor_manager]() {
798 if (editor_manager) {
799 editor_manager->ApplyLayoutPreset("Overworld Expert");
800 }
801 });
802 shortcut_manager->RegisterCommand(
803 "Layout: Apply Dungeon Expert Preset", [editor_manager]() {
804 if (editor_manager) {
805 editor_manager->ApplyLayoutPreset("Dungeon Expert");
806 }
807 });
808 shortcut_manager->RegisterCommand(
809 "Layout: Apply Testing Preset", [editor_manager]() {
810 if (editor_manager) {
811 editor_manager->ApplyLayoutPreset("Testing");
812 }
813 });
814 shortcut_manager->RegisterCommand(
815 "Layout: Apply Audio Preset", [editor_manager]() {
816 if (editor_manager) {
817 editor_manager->ApplyLayoutPreset("Audio");
818 }
819 });
820 shortcut_manager->RegisterCommand(
821 "Layout: Reset Current Editor", [editor_manager]() {
822 if (editor_manager) {
823 editor_manager->ResetCurrentEditorLayout();
824 }
825 });
826
827 // ============================================================================
828 // Right Drawer / Panel Toggle Commands (command palette only)
829 // ============================================================================
830 if (editor_manager) {
831 using DrawerType = RightDrawerManager::DrawerType;
832 auto* right_drawer_manager = editor_manager->right_drawer_manager();
833 if (right_drawer_manager) {
834 struct DrawerCmd {
835 const char* label;
836 DrawerType type;
837 };
838 DrawerCmd drawer_cmds[] = {
839 {"View: Toggle AI Agent Panel", DrawerType::kAgentChat},
840 {"View: Toggle AI Agent Drawer", DrawerType::kAgentChat},
841 {"View: Toggle Proposals Panel", DrawerType::kProposals},
842 {"View: Toggle Proposals Drawer", DrawerType::kProposals},
843 {"View: Toggle Settings Panel", DrawerType::kSettings},
844 {"View: Toggle Settings Drawer", DrawerType::kSettings},
845 {"View: Toggle Help Panel", DrawerType::kHelp},
846 {"View: Toggle Help Drawer", DrawerType::kHelp},
847 {"View: Toggle Notifications", DrawerType::kNotifications},
848 {"View: Toggle Notifications Drawer", DrawerType::kNotifications},
849 {"View: Toggle Properties Panel", DrawerType::kProperties},
850 {"View: Toggle Properties Drawer", DrawerType::kProperties},
851 {"View: Toggle Project Panel", DrawerType::kProject},
852 {"View: Toggle Project Drawer", DrawerType::kProject},
853 };
854 for (const auto& cmd : drawer_cmds) {
855 shortcut_manager->RegisterCommand(
856 cmd.label, [right_drawer_manager, drawer_type = cmd.type]() {
857 right_drawer_manager->ToggleDrawer(drawer_type);
858 });
859 }
860 shortcut_manager->RegisterCommand(
861 "View: Previous Right Panel", [right_drawer_manager]() {
862 right_drawer_manager->CycleToPreviousDrawer();
863 });
864 shortcut_manager->RegisterCommand(
865 "View: Previous Right Drawer", [right_drawer_manager]() {
866 right_drawer_manager->CycleToPreviousDrawer();
867 });
868 shortcut_manager->RegisterCommand(
869 "View: Next Right Panel", [right_drawer_manager]() {
870 right_drawer_manager->CycleToNextDrawer();
871 });
872 shortcut_manager->RegisterCommand(
873 "View: Next Right Drawer", [right_drawer_manager]() {
874 right_drawer_manager->CycleToNextDrawer();
875 });
876 }
877 }
878
879 // ============================================================================
880 // Window + Panel Visibility Commands (command palette only)
881 // ============================================================================
882 if (window_manager) {
883 auto categories = window_manager->GetAllCategories();
884 const size_t registration_session_id = window_manager->GetActiveSessionId();
885
886 shortcut_manager->RegisterCommand(
887 "View: Show Panel Browser",
888 [window_manager]() { window_manager->TriggerShowWindowBrowser(); });
889 shortcut_manager->RegisterCommand(
890 "View: Show Window Browser",
891 [window_manager]() { window_manager->TriggerShowWindowBrowser(); });
892
893 for (const auto& category : categories) {
894 auto windows = window_manager->GetWindowsInCategory(
895 registration_session_id, category);
896 for (const auto& window : windows) {
897 const std::string window_id = window.card_id;
898 const std::string display_name = window.display_name;
899
900 shortcut_manager->RegisterCommand(
901 absl::StrFormat("View: Show %s", display_name),
902 [window_manager, window_id]() {
903 if (window_manager) {
904 window_manager->OpenWindow(window_manager->GetActiveSessionId(),
905 window_id);
906 }
907 });
908 shortcut_manager->RegisterCommand(
909 absl::StrFormat("View: Hide %s", display_name),
910 [window_manager, window_id]() {
911 if (window_manager) {
912 window_manager->CloseWindow(
913 window_manager->GetActiveSessionId(), window_id);
914 }
915 });
916 shortcut_manager->RegisterCommand(
917 absl::StrFormat("View: Toggle %s", display_name),
918 [window_manager, window_id]() {
919 if (window_manager) {
920 window_manager->ToggleWindow(
921 window_manager->GetActiveSessionId(), window_id);
922 }
923 });
924
925 shortcut_manager->RegisterCommand(
926 absl::StrFormat("View: Open %s Window", display_name),
927 [window_manager, window_id]() {
928 if (window_manager) {
929 window_manager->OpenWindow(window_manager->GetActiveSessionId(),
930 window_id);
931 }
932 });
933 shortcut_manager->RegisterCommand(
934 absl::StrFormat("View: Close %s Window", display_name),
935 [window_manager, window_id]() {
936 if (window_manager) {
937 window_manager->CloseWindow(
938 window_manager->GetActiveSessionId(), window_id);
939 }
940 });
941 shortcut_manager->RegisterCommand(
942 absl::StrFormat("View: Toggle %s Window", display_name),
943 [window_manager, window_id]() {
944 if (window_manager) {
945 window_manager->ToggleWindow(
946 window_manager->GetActiveSessionId(), window_id);
947 }
948 });
949 }
950
951 shortcut_manager->RegisterCommand(
952 absl::StrFormat("View: Show All %s Panels", category),
953 [window_manager, category]() {
954 if (window_manager) {
955 window_manager->ShowAllWindowsInCategory(
956 window_manager->GetActiveSessionId(), category);
957 }
958 });
959 shortcut_manager->RegisterCommand(
960 absl::StrFormat("View: Hide All %s Panels", category),
961 [window_manager, category]() {
962 if (window_manager) {
963 window_manager->HideAllWindowsInCategory(
964 window_manager->GetActiveSessionId(), category);
965 }
966 });
967 shortcut_manager->RegisterCommand(
968 absl::StrFormat("View: Show All %s Windows", category),
969 [window_manager, category]() {
970 if (window_manager) {
971 window_manager->ShowAllWindowsInCategory(
972 window_manager->GetActiveSessionId(), category);
973 }
974 });
975 shortcut_manager->RegisterCommand(
976 absl::StrFormat("View: Hide All %s Windows", category),
977 [window_manager, category]() {
978 if (window_manager) {
979 window_manager->HideAllWindowsInCategory(
980 window_manager->GetActiveSessionId(), category);
981 }
982 });
983 }
984 }
985}
986
988 ShortcutManager* shortcut_manager) {
989 if (!shortcut_manager) {
990 return;
991 }
992
993 auto* menu_orchestrator = deps.menu_orchestrator;
994 auto* session_coordinator = deps.session_coordinator;
995 auto* workspace_manager = deps.workspace_manager;
996 auto* editor_manager = deps.editor_manager;
997
998 RegisterIfValid(shortcut_manager, "New Session",
999 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_N},
1000 [session_coordinator]() {
1001 if (session_coordinator) {
1002 session_coordinator->CreateNewSession();
1003 }
1004 });
1005
1006 RegisterIfValid(shortcut_manager, "Duplicate Session",
1007 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_D},
1008 [session_coordinator]() {
1009 if (session_coordinator) {
1010 session_coordinator->DuplicateCurrentSession();
1011 }
1012 });
1013
1014 RegisterIfValid(shortcut_manager, "Close Session",
1015 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_W},
1016 [editor_manager, session_coordinator]() {
1017 if (editor_manager) {
1018 editor_manager->CloseCurrentSession();
1019 } else if (session_coordinator) {
1020 session_coordinator->CloseCurrentSession();
1021 }
1022 });
1023
1024 RegisterIfValid(shortcut_manager, "Session Switcher",
1025 {ImGuiMod_Ctrl, ImGuiKey_Tab}, [session_coordinator]() {
1026 if (session_coordinator) {
1027 session_coordinator->ShowSessionSwitcher();
1028 }
1029 });
1030
1031 RegisterIfValid(shortcut_manager, "Save Layout",
1032 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_L},
1033 [workspace_manager]() {
1034 if (workspace_manager) {
1035 workspace_manager->SaveWorkspaceLayout();
1036 }
1037 });
1038
1039 RegisterIfValid(shortcut_manager, "Load Layout",
1040 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_O},
1041 [workspace_manager]() {
1042 if (workspace_manager) {
1043 workspace_manager->LoadWorkspaceLayout();
1044 }
1045 });
1046
1047 // Note: Changed from Ctrl+Shift+R to Ctrl+Alt+R to avoid conflict with
1048 // Proposal Drawer
1049 RegisterIfValid(shortcut_manager, "Reset Layout",
1050 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_R},
1051 [workspace_manager]() {
1052 if (workspace_manager) {
1053 workspace_manager->ResetWorkspaceLayout();
1054 }
1055 });
1056
1057 RegisterIfValid(shortcut_manager, "Maximize Window", ImGuiKey_F11,
1058 [workspace_manager]() {
1059 if (workspace_manager) {
1060 workspace_manager->MaximizeCurrentWindow();
1061 }
1062 });
1063
1064#ifdef YAZE_ENABLE_TESTING
1065 RegisterIfValid(shortcut_manager, "Test Dashboard",
1066 {ImGuiMod_Ctrl, ImGuiKey_T}, [menu_orchestrator]() {
1067 if (menu_orchestrator) {
1068 menu_orchestrator->OnShowTestDashboard();
1069 }
1070 });
1071#endif
1072}
1073
1075 ShortcutManager* shortcut_manager) {
1076 if (!shortcut_manager || !deps.window_manager) {
1077 return;
1078 }
1079
1080 auto* window_manager = deps.window_manager;
1081 auto* user_settings = deps.user_settings;
1082 size_t session_id = deps.session_coordinator
1084 : 0;
1085
1086 // Get all categories and panels
1087 auto categories = window_manager->GetAllCategories();
1088
1089 for (const auto& category : categories) {
1090 auto panels = window_manager->GetWindowsInCategory(session_id, category);
1091
1092 for (const auto& panel : panels) {
1093 std::string shortcut_string;
1094
1095 // Check for user-defined shortcut first
1096 if (user_settings) {
1097 auto it = user_settings->prefs().panel_shortcuts.find(panel.card_id);
1098 if (it != user_settings->prefs().panel_shortcuts.end()) {
1099 shortcut_string = it->second;
1100 }
1101 }
1102
1103 // Fall back to default shortcut_hint
1104 if (shortcut_string.empty() && !panel.shortcut_hint.empty()) {
1105 shortcut_string = panel.shortcut_hint;
1106 }
1107
1108 // If we have a shortcut, parse and register it
1109 if (!shortcut_string.empty()) {
1110 auto keys = ParseShortcut(shortcut_string);
1111 if (!keys.empty()) {
1112 std::string panel_id_copy = panel.card_id;
1113 // Toggle panel visibility shortcut
1114 if (panel.shortcut_scope == WindowDescriptor::ShortcutScope::kPanel) {
1115 std::string toggle_id = "view.toggle." + panel.card_id;
1116 RegisterIfValid(shortcut_manager, toggle_id, keys,
1117 [window_manager, panel_id_copy]() {
1118 window_manager->ToggleWindow(
1119 window_manager->GetActiveSessionId(),
1120 panel_id_copy);
1121 });
1122 }
1123 }
1124 }
1125 }
1126 }
1127}
1128
1129} // namespace yaze::editor
The EditorManager controls the main editor window and manages the various editor classes.
void SetFontGlobalScale(float scale)
size_t GetActiveSessionId() const
Stable workspace identity that is never reused while this coordinator lives.
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:441
constexpr const char * kSaveAs
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)
std::unordered_map< std::string, std::string > panel_shortcuts