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 "absl/functional/bind_front.h"
4#include "absl/strings/str_format.h"
27#include "core/project.h"
28
29namespace yaze::editor {
30
31namespace {
32
33void RegisterIfValid(ShortcutManager* shortcut_manager, const std::string& name,
34 const std::vector<ImGuiKey>& keys,
35 std::function<void()> callback,
37 if (!shortcut_manager || !callback) {
38 return;
39 }
40 shortcut_manager->RegisterShortcut(name, keys, std::move(callback), scope);
41}
42
43void RegisterIfValid(ShortcutManager* shortcut_manager, const std::string& name,
44 ImGuiKey key, std::function<void()> callback,
46 if (!shortcut_manager || !callback) {
47 return;
48 }
49 shortcut_manager->RegisterShortcut(name, key, std::move(callback), scope);
50}
51
53 std::string id;
54 std::vector<ImGuiKey> keys;
55 std::string description;
56};
57
58const std::vector<EditorShortcutDef> kMusicEditorShortcuts = {
59 {"music.play_pause", {ImGuiKey_Space}, "Play/Pause current song"},
60 {"music.stop", {ImGuiKey_Escape}, "Stop playback"},
61 {"music.speed_up", {ImGuiKey_Equal}, "Increase playback speed"},
62 {"music.speed_up_keypad",
63 {ImGuiKey_KeypadAdd},
64 "Increase playback speed (keypad)"},
65 {"music.speed_down", {ImGuiKey_Minus}, "Decrease playback speed"},
66 {"music.speed_down_keypad",
67 {ImGuiKey_KeypadSubtract},
68 "Decrease playback speed (keypad)"},
69};
70
71const std::vector<EditorShortcutDef> kDungeonEditorShortcuts = {
72 {"dungeon.object.select_tool", {ImGuiKey_S}, "Select tool"},
73 {"dungeon.object.place_tool", {ImGuiKey_P}, "Place tool"},
74 {"dungeon.object.delete_tool", {ImGuiKey_D}, "Delete tool"},
75 {"dungeon.object.next_object", {ImGuiKey_RightBracket}, "Next object"},
76 {"dungeon.object.prev_object", {ImGuiKey_LeftBracket}, "Previous object"},
77 {"dungeon.object.copy", {ImGuiMod_Ctrl, ImGuiKey_C}, "Copy selection"},
78 {"dungeon.object.paste", {ImGuiMod_Ctrl, ImGuiKey_V}, "Paste selection"},
79 {"dungeon.object.delete", {ImGuiKey_Delete}, "Delete selection"},
80};
81
82const std::vector<EditorShortcutDef> kOverworldShortcuts = {
83 {"overworld.brush_toggle", {ImGuiKey_B}, "Toggle brush"},
84 {"overworld.fill", {ImGuiKey_F}, "Fill tool"},
85 {"overworld.next_tile", {ImGuiKey_RightBracket}, "Next tile"},
86 {"overworld.prev_tile", {ImGuiKey_LeftBracket}, "Previous tile"},
87};
88
89const std::vector<EditorShortcutDef> kGraphicsShortcuts = {
90 // Sheet navigation
91 {"graphics.next_sheet", {ImGuiKey_PageDown}, "Next sheet"},
92 {"graphics.prev_sheet", {ImGuiKey_PageUp}, "Previous sheet"},
93
94 // Tool selection shortcuts
95 {"graphics.tool.select", {ImGuiKey_V}, "Select tool"},
96 {"graphics.tool.pencil", {ImGuiKey_B}, "Pencil tool"},
97 {"graphics.tool.brush", {ImGuiKey_P}, "Brush tool"},
98 {"graphics.tool.eraser", {ImGuiKey_E}, "Eraser tool"},
99 {"graphics.tool.fill", {ImGuiKey_G}, "Fill tool"},
100 {"graphics.tool.line", {ImGuiKey_L}, "Line tool"},
101 {"graphics.tool.rectangle", {ImGuiKey_R}, "Rectangle tool"},
102 {"graphics.tool.eyedropper", {ImGuiKey_I}, "Eyedropper tool"},
103
104 // Zoom controls
105 {"graphics.zoom_in", {ImGuiKey_Equal}, "Zoom in"},
106 {"graphics.zoom_in_keypad", {ImGuiKey_KeypadAdd}, "Zoom in (keypad)"},
107 {"graphics.zoom_out", {ImGuiKey_Minus}, "Zoom out"},
108 {"graphics.zoom_out_keypad",
109 {ImGuiKey_KeypadSubtract},
110 "Zoom out (keypad)"},
111
112 // View toggles
113 {"graphics.toggle_grid", {ImGuiMod_Ctrl, ImGuiKey_G}, "Toggle grid"},
114};
115
116} // namespace
117
119 ShortcutManager* shortcut_manager) {
120 if (!shortcut_manager) {
121 return;
122 }
123
124 auto* editor_manager = deps.editor_manager;
125 auto* ui_coordinator = deps.ui_coordinator;
126 auto* popup_manager = deps.popup_manager;
127 auto* panel_manager = deps.panel_manager;
128
129 // Toggle activity bar (48px icon strip) visibility
130 RegisterIfValid(
131 shortcut_manager, "view.toggle_activity_bar", {ImGuiMod_Ctrl, ImGuiKey_B},
132 [panel_manager]() {
133 if (panel_manager) {
134 panel_manager->ToggleSidebarVisibility();
135 }
136 },
138
139 // Toggle side panel (250px expanded panel) expansion
140 RegisterIfValid(
141 shortcut_manager, "view.toggle_side_panel",
142 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_E},
143 [panel_manager]() {
144 if (panel_manager) {
145 panel_manager->TogglePanelExpanded();
146 }
147 },
149
150 RegisterIfValid(
151 shortcut_manager, "Open", {ImGuiMod_Ctrl, ImGuiKey_O},
152 [editor_manager]() {
153 if (editor_manager) {
154 editor_manager->LoadRom();
155 }
156 },
158
159 RegisterIfValid(shortcut_manager, "Save", {ImGuiMod_Ctrl, ImGuiKey_S},
160 [editor_manager]() {
161 if (editor_manager) {
162 editor_manager->SaveRom();
163 }
164 });
165
166 RegisterIfValid(
167 shortcut_manager, "Save As", {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_S},
168 [editor_manager]() {
169 if (editor_manager) {
170 // Use project-aware default filename when possible
171 std::string filename =
172 editor_manager->GetCurrentRom()
173 ? editor_manager->GetCurrentRom()->filename()
174 : "";
175 editor_manager->SaveRomAs(filename);
176 }
177 },
179
180 RegisterIfValid(
181 shortcut_manager, "Close ROM", {ImGuiMod_Ctrl, ImGuiKey_W},
182 [editor_manager]() {
183 if (editor_manager && editor_manager->GetCurrentRom()) {
184 editor_manager->GetCurrentRom()->Close();
185 }
186 },
188
189 RegisterIfValid(
190 shortcut_manager, "Quit", {ImGuiMod_Ctrl, ImGuiKey_Q},
191 [editor_manager]() {
192 if (editor_manager) {
193 editor_manager->Quit();
194 }
195 },
197
198 RegisterIfValid(
199 shortcut_manager, "Undo", {ImGuiMod_Ctrl, ImGuiKey_Z},
200 [editor_manager]() {
201 if (editor_manager && editor_manager->GetCurrentEditor()) {
202 editor_manager->GetCurrentEditor()->Undo();
203 }
204 },
206
207 RegisterIfValid(
208 shortcut_manager, "Redo", {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_Z},
209 [editor_manager]() {
210 if (editor_manager && editor_manager->GetCurrentEditor()) {
211 editor_manager->GetCurrentEditor()->Redo();
212 }
213 },
215
216 RegisterIfValid(
217 shortcut_manager, "Cut", {ImGuiMod_Ctrl, ImGuiKey_X},
218 [editor_manager]() {
219 if (editor_manager && editor_manager->GetCurrentEditor()) {
220 editor_manager->GetCurrentEditor()->Cut();
221 }
222 },
224
225 RegisterIfValid(
226 shortcut_manager, "Copy", {ImGuiMod_Ctrl, ImGuiKey_C},
227 [editor_manager]() {
228 if (editor_manager && editor_manager->GetCurrentEditor()) {
229 editor_manager->GetCurrentEditor()->Copy();
230 }
231 },
233
234 RegisterIfValid(
235 shortcut_manager, "Paste", {ImGuiMod_Ctrl, ImGuiKey_V},
236 [editor_manager]() {
237 if (editor_manager && editor_manager->GetCurrentEditor()) {
238 editor_manager->GetCurrentEditor()->Paste();
239 }
240 },
242
243 RegisterIfValid(
244 shortcut_manager, "Find", {ImGuiMod_Ctrl, ImGuiKey_F},
245 [editor_manager]() {
246 if (editor_manager && editor_manager->GetCurrentEditor()) {
247 editor_manager->GetCurrentEditor()->Find();
248 }
249 },
251
252 RegisterIfValid(
253 shortcut_manager, "Command Palette",
254 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_P},
255 [ui_coordinator]() {
256 if (ui_coordinator) {
257 ui_coordinator->ShowCommandPalette();
258 }
259 },
261
262 RegisterIfValid(
263 shortcut_manager, "Global Search",
264 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_K},
265 [ui_coordinator]() {
266 if (ui_coordinator) {
267 ui_coordinator->ShowGlobalSearch();
268 }
269 },
271
272 RegisterIfValid(
273 shortcut_manager, "Load Last ROM", {ImGuiMod_Ctrl, ImGuiKey_R},
274 [editor_manager]() {
276 if (!recent.GetRecentFiles().empty() && editor_manager) {
277 editor_manager->OpenRomOrProject(recent.GetRecentFiles().front());
278 }
279 },
281
282 RegisterIfValid(
283 shortcut_manager, "Show About", ImGuiKey_F1,
284 [popup_manager]() {
285 if (popup_manager) {
286 popup_manager->Show("About");
287 }
288 },
290
291 auto register_editor_shortcut = [&](EditorType type, ImGuiKey key) {
292 RegisterIfValid(shortcut_manager,
293 absl::StrFormat("switch.%d", static_cast<int>(type)),
294 {ImGuiMod_Ctrl, key}, [editor_manager, type]() {
295 if (editor_manager) {
296 editor_manager->SwitchToEditor(type);
297 }
298 });
299 };
300
301 register_editor_shortcut(EditorType::kOverworld, ImGuiKey_1);
302 register_editor_shortcut(EditorType::kDungeon, ImGuiKey_2);
303 register_editor_shortcut(EditorType::kGraphics, ImGuiKey_3);
304 register_editor_shortcut(EditorType::kSprite, ImGuiKey_4);
305 register_editor_shortcut(EditorType::kMessage, ImGuiKey_5);
306 register_editor_shortcut(EditorType::kMusic, ImGuiKey_6);
307 register_editor_shortcut(EditorType::kPalette, ImGuiKey_7);
308 register_editor_shortcut(EditorType::kScreen, ImGuiKey_8);
309 register_editor_shortcut(EditorType::kAssembly, ImGuiKey_9);
310 register_editor_shortcut(EditorType::kSettings, ImGuiKey_0);
311
312 // ============================================================================
313 // Editor Switch Commands (command palette with friendly names)
314 // ============================================================================
315 auto register_editor_command = [&](EditorType type, const std::string& name) {
316 shortcut_manager->RegisterCommand(
317 absl::StrFormat("Switch to %s Editor", name), [editor_manager, type]() {
318 if (editor_manager) {
319 editor_manager->SwitchToEditor(type);
320 }
321 });
322 };
323
324 register_editor_command(EditorType::kOverworld, "Overworld");
325 register_editor_command(EditorType::kDungeon, "Dungeon");
326 register_editor_command(EditorType::kGraphics, "Graphics");
327 register_editor_command(EditorType::kSprite, "Sprite");
328 register_editor_command(EditorType::kMessage, "Message");
329 register_editor_command(EditorType::kMusic, "Music");
330 register_editor_command(EditorType::kPalette, "Palette");
331 register_editor_command(EditorType::kScreen, "Screen");
332 register_editor_command(EditorType::kAssembly, "Assembly");
333 register_editor_command(EditorType::kSettings, "Settings");
334
335 // Editor-scoped Music shortcuts (toggle playback, speed controls)
336 if (editor_manager) {
337 for (const auto& def : kMusicEditorShortcuts) {
338 RegisterIfValid(
339 shortcut_manager, def.id, def.keys,
340 [editor_manager, id = def.id]() {
341 if (!editor_manager)
342 return;
343 auto* current_editor = editor_manager->GetCurrentEditor();
344 if (!current_editor ||
345 current_editor->type() != EditorType::kMusic) {
346 return;
347 }
348 auto* editor_set = editor_manager->GetCurrentEditorSet();
349 auto* music_editor =
350 editor_set ? editor_set->GetMusicEditor() : nullptr;
351 if (!music_editor)
352 return;
353
354 if (id == "music.play_pause") {
355 music_editor->TogglePlayPause();
356 } else if (id == "music.stop") {
357 music_editor->StopPlayback();
358 } else if (id == "music.speed_up" ||
359 id == "music.speed_up_keypad") {
360 music_editor->SpeedUp();
361 } else if (id == "music.speed_down" ||
362 id == "music.speed_down_keypad") {
363 music_editor->SlowDown();
364 }
365 },
367 }
368 }
369
370 // Editor-scoped Dungeon shortcuts (object tools)
371 if (editor_manager) {
372 for (const auto& def : kDungeonEditorShortcuts) {
373 RegisterIfValid(
374 shortcut_manager, def.id, def.keys,
375 [editor_manager, id = def.id]() {
376 if (!editor_manager)
377 return;
378 auto* current_editor = editor_manager->GetCurrentEditor();
379 if (!current_editor ||
380 current_editor->type() != EditorType::kDungeon) {
381 return;
382 }
383 auto* editor_set = editor_manager->GetCurrentEditorSet();
384 auto* dungeon_editor =
385 editor_set ? editor_set->GetDungeonEditor() : nullptr;
386 if (!dungeon_editor)
387 return;
388 auto* obj_panel = dungeon_editor->object_editor_panel();
389 if (!obj_panel)
390 return;
391
392 if (id == "dungeon.object.select_tool") {
393 // Unified mode: cancel placement to switch to selection
394 obj_panel->CancelPlacement();
395 } else if (id == "dungeon.object.place_tool") {
396 // Unified mode: handled by object selector click
397 // No-op (mode is controlled by selecting an object)
398 } else if (id == "dungeon.object.delete_tool") {
399 // Unified mode: delete selected objects
400 obj_panel->DeleteSelectedObjects();
401 } else if (id == "dungeon.object.next_object") {
402 obj_panel->CycleObjectSelection(1);
403 } else if (id == "dungeon.object.prev_object") {
404 obj_panel->CycleObjectSelection(-1);
405 } else if (id == "dungeon.object.copy") {
406 obj_panel->CopySelectedObjects();
407 } else if (id == "dungeon.object.paste") {
408 obj_panel->PasteObjects();
409 } else if (id == "dungeon.object.delete") {
410 obj_panel->DeleteSelectedObjects();
411 }
412 },
414 }
415 }
416
417 // Editor-scoped Overworld shortcuts (basic tools)
418 if (editor_manager) {
419 for (const auto& def : kOverworldShortcuts) {
421 shortcut_manager, def.id, def.keys,
422 [editor_manager, id = def.id]() {
423 if (!editor_manager)
424 return;
425 auto* current_editor = editor_manager->GetCurrentEditor();
426 if (!current_editor ||
427 current_editor->type() != EditorType::kOverworld) {
428 return;
429 }
430 auto* editor_set = editor_manager->GetCurrentEditorSet();
431 auto* overworld_editor =
432 editor_set ? editor_set->GetOverworldEditor() : nullptr;
433 if (!overworld_editor)
434 return;
435
436 if (id == "overworld.brush_toggle") {
437 overworld_editor->ToggleBrushTool();
438 } else if (id == "overworld.fill") {
439 overworld_editor->ActivateFillTool();
440 } else if (id == "overworld.next_tile") {
441 overworld_editor->CycleTileSelection(1);
442 } else if (id == "overworld.prev_tile") {
443 overworld_editor->CycleTileSelection(-1);
444 }
445 },
446 Shortcut::Scope::kEditor);
447 }
448 }
449
450 // Editor-scoped Graphics shortcuts (sheet navigation)
451 if (editor_manager) {
452 for (const auto& def : kGraphicsShortcuts) {
454 shortcut_manager, def.id, def.keys,
455 [editor_manager, id = def.id]() {
456 if (!editor_manager)
457 return;
458 auto* current_editor = editor_manager->GetCurrentEditor();
459 if (!current_editor ||
460 current_editor->type() != EditorType::kGraphics) {
461 return;
462 }
463 auto* editor_set = editor_manager->GetCurrentEditorSet();
464 auto* graphics_editor =
465 editor_set ? editor_set->GetGraphicsEditor() : nullptr;
466 if (!graphics_editor)
467 return;
468
469 if (id == "graphics.next_sheet") {
470 graphics_editor->NextSheet();
471 } else if (id == "graphics.prev_sheet") {
472 graphics_editor->PrevSheet();
473 }
474 },
475 Shortcut::Scope::kEditor);
476 }
477 }
478
480 shortcut_manager, "Editor Selection", {ImGuiMod_Ctrl, ImGuiKey_E},
481 [ui_coordinator]() {
482 if (ui_coordinator) {
483 ui_coordinator->ShowEditorSelection();
484 }
485 },
486 Shortcut::Scope::kGlobal);
487
489 shortcut_manager, "Panel Browser",
490 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_B},
491 [ui_coordinator]() {
492 if (ui_coordinator) {
493 ui_coordinator->ShowPanelBrowser();
494 }
495 },
496 Shortcut::Scope::kGlobal);
498 shortcut_manager, "Panel Browser (Alt)",
499 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_P},
500 [ui_coordinator]() {
501 if (ui_coordinator) {
502 ui_coordinator->ShowPanelBrowser();
503 }
504 },
505 Shortcut::Scope::kGlobal);
506
508 shortcut_manager, "View: Previous Right Panel",
509 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_LeftBracket},
510 [editor_manager]() {
511 if (!editor_manager) {
512 return;
513 }
514 if (auto* right_panel = editor_manager->right_panel_manager()) {
515 right_panel->CycleToPreviousPanel();
516 }
517 },
518 Shortcut::Scope::kGlobal);
519
521 shortcut_manager, "View: Next Right Panel",
522 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_RightBracket},
523 [editor_manager]() {
524 if (!editor_manager) {
525 return;
526 }
527 if (auto* right_panel = editor_manager->right_panel_manager()) {
528 right_panel->CycleToNextPanel();
529 }
530 },
531 Shortcut::Scope::kGlobal);
532
533 if (panel_manager) {
534 // Note: Using Ctrl+Alt for panel shortcuts to avoid conflicts with Save As
535 // (Ctrl+Shift+S)
537 shortcut_manager, "Show Dungeon Panels",
538 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_D},
539 [panel_manager]() {
540 panel_manager->ShowAllPanelsInCategory(0, "Dungeon");
541 },
542 Shortcut::Scope::kEditor);
544 shortcut_manager, "Show Graphics Panels",
545 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_G},
546 [panel_manager]() {
547 panel_manager->ShowAllPanelsInCategory(0, "Graphics");
548 },
549 Shortcut::Scope::kEditor);
551 shortcut_manager, "Show Screen Panels",
552 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_S},
553 [panel_manager]() {
554 panel_manager->ShowAllPanelsInCategory(0, "Screen");
555 },
556 Shortcut::Scope::kEditor);
557 }
558
559#ifdef YAZE_BUILD_AGENT_UI
560 RegisterIfValid(shortcut_manager, "Agent Editor",
561 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_A},
562 [editor_manager]() {
563 if (editor_manager) {
564 editor_manager->ShowAIAgent();
565 }
566 });
567
568 RegisterIfValid(shortcut_manager, "Agent Sidebar",
569 {ImGuiMod_Ctrl, ImGuiKey_H}, [editor_manager]() {
570 if (editor_manager) {
571 editor_manager->ShowChatHistory();
572 }
573 });
574
575 RegisterIfValid(shortcut_manager, "Proposal Drawer",
576 {ImGuiMod_Ctrl, ImGuiMod_Shift,
577 ImGuiKey_R}, // Changed from Ctrl+P to Ctrl+Shift+R
578 [editor_manager]() {
579 if (editor_manager) {
580 editor_manager->ShowProposalDrawer();
581 }
582 });
583#endif
584
585 // ============================================================================
586 // Layout Presets and Profiles (command palette only - no keyboard shortcuts)
587 // ============================================================================
588 shortcut_manager->RegisterCommand("Layout Profile: Code", [editor_manager]() {
589 if (editor_manager) {
590 editor_manager->ApplyLayoutProfile("code");
591 }
592 });
593 shortcut_manager->RegisterCommand(
594 "Layout Profile: Debug", [editor_manager]() {
595 if (editor_manager) {
596 editor_manager->ApplyLayoutProfile("debug");
597 }
598 });
599 shortcut_manager->RegisterCommand(
600 "Layout Profile: Mapping", [editor_manager]() {
601 if (editor_manager) {
602 editor_manager->ApplyLayoutProfile("mapping");
603 }
604 });
605 shortcut_manager->RegisterCommand("Layout Profile: Chat", [editor_manager]() {
606 if (editor_manager) {
607 editor_manager->ApplyLayoutProfile("chat");
608 }
609 });
610 shortcut_manager->RegisterCommand(
611 "Layout Snapshot: Capture", [editor_manager]() {
612 if (editor_manager) {
613 editor_manager->CaptureTemporaryLayoutSnapshot();
614 }
615 });
616 shortcut_manager->RegisterCommand(
617 "Layout Snapshot: Restore", [editor_manager]() {
618 if (editor_manager) {
619 editor_manager->RestoreTemporaryLayoutSnapshot();
620 }
621 });
622 shortcut_manager->RegisterCommand(
623 "Layout Snapshot: Clear", [editor_manager]() {
624 if (editor_manager) {
625 editor_manager->ClearTemporaryLayoutSnapshot();
626 }
627 });
628
629 shortcut_manager->RegisterCommand(
630 "Layout: Apply Minimal Preset", [editor_manager]() {
631 if (editor_manager) {
632 editor_manager->ApplyLayoutPreset("Minimal");
633 }
634 });
635 shortcut_manager->RegisterCommand(
636 "Layout: Apply Developer Preset", [editor_manager]() {
637 if (editor_manager) {
638 editor_manager->ApplyLayoutPreset("Developer");
639 }
640 });
641 shortcut_manager->RegisterCommand(
642 "Layout: Apply Designer Preset", [editor_manager]() {
643 if (editor_manager) {
644 editor_manager->ApplyLayoutPreset("Designer");
645 }
646 });
647 shortcut_manager->RegisterCommand(
648 "Layout: Apply Modder Preset", [editor_manager]() {
649 if (editor_manager) {
650 editor_manager->ApplyLayoutPreset("Modder");
651 }
652 });
653 shortcut_manager->RegisterCommand(
654 "Layout: Apply Overworld Expert Preset", [editor_manager]() {
655 if (editor_manager) {
656 editor_manager->ApplyLayoutPreset("Overworld Expert");
657 }
658 });
659 shortcut_manager->RegisterCommand(
660 "Layout: Apply Dungeon Expert Preset", [editor_manager]() {
661 if (editor_manager) {
662 editor_manager->ApplyLayoutPreset("Dungeon Expert");
663 }
664 });
665 shortcut_manager->RegisterCommand(
666 "Layout: Apply Testing Preset", [editor_manager]() {
667 if (editor_manager) {
668 editor_manager->ApplyLayoutPreset("Testing");
669 }
670 });
671 shortcut_manager->RegisterCommand(
672 "Layout: Apply Audio Preset", [editor_manager]() {
673 if (editor_manager) {
674 editor_manager->ApplyLayoutPreset("Audio");
675 }
676 });
677 shortcut_manager->RegisterCommand(
678 "Layout: Reset Current Editor", [editor_manager]() {
679 if (editor_manager) {
680 editor_manager->ResetCurrentEditorLayout();
681 }
682 });
683
684 // ============================================================================
685 // Right Panel Toggle Commands (command palette only)
686 // ============================================================================
687 if (editor_manager) {
688 using PanelType = RightPanelManager::PanelType;
689 auto* rpm = editor_manager->right_panel_manager();
690 if (rpm) {
691 struct PanelCmd {
692 const char* label;
693 PanelType type;
694 };
695 PanelCmd panel_cmds[] = {
696 {"View: Toggle AI Agent Panel", PanelType::kAgentChat},
697 {"View: Toggle Proposals Panel", PanelType::kProposals},
698 {"View: Toggle Settings Panel", PanelType::kSettings},
699 {"View: Toggle Help Panel", PanelType::kHelp},
700 {"View: Toggle Notifications", PanelType::kNotifications},
701 {"View: Toggle Properties Panel", PanelType::kProperties},
702 {"View: Toggle Project Panel", PanelType::kProject},
703 };
704 for (const auto& cmd : panel_cmds) {
705 shortcut_manager->RegisterCommand(
706 cmd.label,
707 [rpm, panel_type = cmd.type]() { rpm->TogglePanel(panel_type); });
708 }
709 shortcut_manager->RegisterCommand("View: Previous Right Panel", [rpm]() {
710 rpm->CycleToPreviousPanel();
711 });
712 shortcut_manager->RegisterCommand("View: Next Right Panel",
713 [rpm]() { rpm->CycleToNextPanel(); });
714 }
715 }
716
717 // ============================================================================
718 // Panel Visibility Toggle Commands (command palette only)
719 // ============================================================================
720 if (panel_manager) {
721 auto categories = panel_manager->GetAllCategories();
722 int session_id = 0; // Default session for command registration
723
724 for (const auto& category : categories) {
725 auto panels = panel_manager->GetPanelsInCategory(session_id, category);
726
727 for (const auto& panel : panels) {
728 std::string panel_id = panel.card_id;
729 std::string display_name = panel.display_name;
730
731 // Register show command
732 shortcut_manager->RegisterCommand(
733 absl::StrFormat("View: Show %s", display_name),
734 [panel_manager, panel_id]() {
735 if (panel_manager) {
736 panel_manager->ShowPanel(0, panel_id);
737 }
738 });
739
740 // Register hide command
741 shortcut_manager->RegisterCommand(
742 absl::StrFormat("View: Hide %s", display_name),
743 [panel_manager, panel_id]() {
744 if (panel_manager) {
745 panel_manager->HidePanel(0, panel_id);
746 }
747 });
748
749 // Register toggle command
750 shortcut_manager->RegisterCommand(
751 absl::StrFormat("View: Toggle %s", display_name),
752 [panel_manager, panel_id]() {
753 if (panel_manager) {
754 panel_manager->TogglePanel(0, panel_id);
755 }
756 });
757 }
758 }
759
760 // Category-level commands
761 for (const auto& category : categories) {
762 shortcut_manager->RegisterCommand(
763 absl::StrFormat("View: Show All %s Panels", category),
764 [panel_manager, category]() {
765 if (panel_manager) {
766 panel_manager->ShowAllPanelsInCategory(0, category);
767 }
768 });
769
770 shortcut_manager->RegisterCommand(
771 absl::StrFormat("View: Hide All %s Panels", category),
772 [panel_manager, category]() {
773 if (panel_manager) {
774 panel_manager->HideAllPanelsInCategory(0, category);
775 }
776 });
777 }
778 }
779}
780
782 ShortcutManager* shortcut_manager) {
783 if (!shortcut_manager) {
784 return;
785 }
786
787 auto* menu_orchestrator = deps.menu_orchestrator;
788 auto* session_coordinator = deps.session_coordinator;
789 auto* workspace_manager = deps.workspace_manager;
790
791 RegisterIfValid(shortcut_manager, "New Session",
792 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_N},
793 [session_coordinator]() {
794 if (session_coordinator) {
795 session_coordinator->CreateNewSession();
796 }
797 });
798
799 RegisterIfValid(shortcut_manager, "Duplicate Session",
800 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_D},
801 [session_coordinator]() {
802 if (session_coordinator) {
803 session_coordinator->DuplicateCurrentSession();
804 }
805 });
806
807 RegisterIfValid(shortcut_manager, "Close Session",
808 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_W},
809 [session_coordinator]() {
810 if (session_coordinator) {
811 session_coordinator->CloseCurrentSession();
812 }
813 });
814
815 RegisterIfValid(shortcut_manager, "Session Switcher",
816 {ImGuiMod_Ctrl, ImGuiKey_Tab}, [session_coordinator]() {
817 if (session_coordinator) {
818 session_coordinator->ShowSessionSwitcher();
819 }
820 });
821
822 RegisterIfValid(shortcut_manager, "Save Layout",
823 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_L},
824 [workspace_manager]() {
825 if (workspace_manager) {
826 workspace_manager->SaveWorkspaceLayout();
827 }
828 });
829
830 RegisterIfValid(shortcut_manager, "Load Layout",
831 {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_O},
832 [workspace_manager]() {
833 if (workspace_manager) {
834 workspace_manager->LoadWorkspaceLayout();
835 }
836 });
837
838 // Note: Changed from Ctrl+Shift+R to Ctrl+Alt+R to avoid conflict with
839 // Proposal Drawer
840 RegisterIfValid(shortcut_manager, "Reset Layout",
841 {ImGuiMod_Ctrl, ImGuiMod_Alt, ImGuiKey_R},
842 [workspace_manager]() {
843 if (workspace_manager) {
844 workspace_manager->ResetWorkspaceLayout();
845 }
846 });
847
848 RegisterIfValid(shortcut_manager, "Maximize Window", ImGuiKey_F11,
849 [workspace_manager]() {
850 if (workspace_manager) {
851 workspace_manager->MaximizeCurrentWindow();
852 }
853 });
854
855#ifdef YAZE_ENABLE_TESTING
856 RegisterIfValid(shortcut_manager, "Test Dashboard",
857 {ImGuiMod_Ctrl, ImGuiKey_T}, [menu_orchestrator]() {
858 if (menu_orchestrator) {
859 menu_orchestrator->OnShowTestDashboard();
860 }
861 });
862#endif
863}
864
866 ShortcutManager* shortcut_manager) {
867 if (!shortcut_manager || !deps.panel_manager) {
868 return;
869 }
870
871 auto* panel_manager = deps.panel_manager;
872 auto* user_settings = deps.user_settings;
873 int session_id = deps.session_coordinator
875 : 0;
876
877 // Get all categories and panels
878 auto categories = panel_manager->GetAllCategories();
879
880 for (const auto& category : categories) {
881 auto panels = panel_manager->GetPanelsInCategory(session_id, category);
882
883 for (const auto& panel : panels) {
884 std::string shortcut_string;
885
886 // Check for user-defined shortcut first
887 if (user_settings) {
888 auto it = user_settings->prefs().panel_shortcuts.find(panel.card_id);
889 if (it != user_settings->prefs().panel_shortcuts.end()) {
890 shortcut_string = it->second;
891 }
892 }
893
894 // Fall back to default shortcut_hint
895 if (shortcut_string.empty() && !panel.shortcut_hint.empty()) {
896 shortcut_string = panel.shortcut_hint;
897 }
898
899 // If we have a shortcut, parse and register it
900 if (!shortcut_string.empty()) {
901 auto keys = ParseShortcut(shortcut_string);
902 if (!keys.empty()) {
903 std::string panel_id_copy = panel.card_id;
904 // Toggle panel visibility shortcut
905 if (panel.shortcut_scope == PanelDescriptor::ShortcutScope::kPanel) {
906 std::string toggle_id = "view.toggle." + panel.card_id;
907 RegisterIfValid(shortcut_manager, toggle_id, keys,
908 [panel_manager, panel_id_copy, session_id]() {
909 panel_manager->TogglePanel(session_id,
910 panel_id_copy);
911 });
912 }
913 }
914 }
915 }
916 }
917}
918
919} // namespace yaze::editor
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:374
void RegisterIfValid(ShortcutManager *shortcut_manager, const std::string &name, const std::vector< ImGuiKey > &keys, std::function< void()> callback, Shortcut::Scope scope=Shortcut::Scope::kGlobal)
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)