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