yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
menu_orchestrator.cc
Go to the documentation of this file.
1#include "menu_orchestrator.h"
2
3#include "absl/status/status.h"
4#include "absl/strings/str_format.h"
5#include "app/editor/editor.h"
16#include "app/gui/core/icons.h"
18#include "core/features.h"
19#include "rom/rom.h"
21
22// Platform-aware shortcut macros for menu display
23#define SHORTCUT_CTRL(key) gui::FormatCtrlShortcut(ImGuiKey_##key).c_str()
24#define SHORTCUT_CTRL_SHIFT(key) \
25 gui::FormatCtrlShiftShortcut(ImGuiKey_##key).c_str()
26
27namespace yaze {
28namespace editor {
29
31 EditorManager* editor_manager, MenuBuilder& menu_builder,
32 RomFileManager& rom_manager, ProjectManager& project_manager,
33 EditorRegistry& editor_registry, SessionCoordinator& session_coordinator,
34 ToastManager& toast_manager, PopupManager& popup_manager)
35 : editor_manager_(editor_manager),
36 menu_builder_(menu_builder),
37 rom_manager_(rom_manager),
38 project_manager_(project_manager),
39 editor_registry_(editor_registry),
40 session_coordinator_(session_coordinator),
41 toast_manager_(toast_manager),
42 popup_manager_(popup_manager) {}
43
45 ClearMenu();
46
47 // Build all menu sections in order
48 // Traditional order: File, Edit, View, then app-specific menus
52 BuildPanelsMenu(); // Dedicated top-level menu for panel management
53 BuildToolsMenu(); // Debug menu items merged into Tools
56
57 // Draw the constructed menu
59
60 menu_needs_refresh_ = false;
61}
62
68
70 // ROM Operations
72 .Item(
73 "Open ROM / Project...", ICON_MD_FILE_OPEN, [this]() { OnOpenRom(); },
75 .Item(
76 "Save ROM", ICON_MD_SAVE, [this]() { OnSaveRom(); }, SHORTCUT_CTRL(S),
77 [this]() { return CanSaveRom(); })
78 .Item(
79 "Save As...", ICON_MD_SAVE_AS, [this]() { OnSaveRomAs(); }, nullptr,
80 [this]() { return CanSaveRom(); })
81 .Item("Save Scope...", ICON_MD_TUNE,
83 .Separator();
84
85 // Project Operations
87 .Item("New Project", ICON_MD_CREATE_NEW_FOLDER,
88 [this]() { OnCreateProject(); })
89 .Item("Open Project Only...", ICON_MD_FOLDER_OPEN,
90 [this]() { OnOpenProject(); })
91 .Item(
92 "Save Project", ICON_MD_SAVE, [this]() { OnSaveProject(); }, nullptr,
93 [this]() { return CanSaveProject(); })
94 .Item(
95 "Save Project As...", ICON_MD_SAVE_AS,
96 [this]() { OnSaveProjectAs(); }, nullptr,
97 [this]() { return CanSaveProject(); })
98 .Item(
99 "Project Management...", ICON_MD_FOLDER_SPECIAL,
100 [this]() { OnShowProjectManagement(); }, nullptr,
101 [this]() { return CanSaveProject(); })
102 .Item(
103 "Edit Project File...", ICON_MD_DESCRIPTION,
104 [this]() { OnShowProjectFileEditor(); }, nullptr,
105 [this]() { return HasProjectFile(); })
106 .Separator();
107
108 // ROM Information and Validation
110 .Item(
111 "ROM Information", ICON_MD_INFO, [this]() { OnShowRomInfo(); },
112 nullptr, [this]() { return HasActiveRom(); })
113 .Item(
114 "Create Backup", ICON_MD_BACKUP, [this]() { OnCreateBackup(); },
115 nullptr, [this]() { return HasActiveRom(); })
116 .Item(
117 "ROM Backups...", ICON_MD_BACKUP,
118 [this]() { popup_manager_.Show(PopupID::kRomBackups); }, nullptr,
119 [this]() { return HasActiveRom(); })
120 .Item(
121 "Validate ROM", ICON_MD_CHECK_CIRCLE, [this]() { OnValidateRom(); },
122 nullptr, [this]() { return HasActiveRom(); })
123 .Separator();
124
125 // Settings and Quit
127 .Item("Settings", ICON_MD_SETTINGS, [this]() { OnShowSettings(); })
128 .Separator()
129 .Item(
130 "Quit", ICON_MD_EXIT_TO_APP, [this]() { OnQuit(); },
131 SHORTCUT_CTRL(Q));
132}
133
139
141 // Undo/Redo operations - delegate to current editor
143 .Item(
144 "Undo", ICON_MD_UNDO, [this]() { OnUndo(); }, SHORTCUT_CTRL(Z),
145 [this]() { return HasCurrentEditor(); })
146 .Item(
147 "Redo", ICON_MD_REDO, [this]() { OnRedo(); }, SHORTCUT_CTRL(Y),
148 [this]() { return HasCurrentEditor(); })
149 .Separator();
150
151 // Clipboard operations - delegate to current editor
153 .Item(
154 "Cut", ICON_MD_CONTENT_CUT, [this]() { OnCut(); }, SHORTCUT_CTRL(X),
155 [this]() { return HasCurrentEditor(); })
156 .Item(
157 "Copy", ICON_MD_CONTENT_COPY, [this]() { OnCopy(); },
158 SHORTCUT_CTRL(C), [this]() { return HasCurrentEditor(); })
159 .Item(
160 "Paste", ICON_MD_CONTENT_PASTE, [this]() { OnPaste(); },
161 SHORTCUT_CTRL(V), [this]() { return HasCurrentEditor(); })
162 .Separator();
163
164 // Search operations (Find in Files moved to Tools > Global Search)
166 "Find", ICON_MD_SEARCH, [this]() { OnFind(); }, SHORTCUT_CTRL(F),
167 [this]() { return HasCurrentEditor(); });
168}
169
175
179
182
183 // Editor selection (Switch Editor)
185 "Switch Editor...", ICON_MD_SWAP_HORIZ,
186 [this]() { OnShowEditorSelection(); }, SHORTCUT_CTRL(E),
187 [this]() { return HasActiveRom(); });
188}
189
191 // Appearance/Layout controls
193 .Item(
194 "Show Sidebar", ICON_MD_VIEW_SIDEBAR,
195 [this]() {
196 if (panel_manager_)
198 },
199 SHORTCUT_CTRL(B), nullptr,
200 [this]() {
202 })
203 .Item(
204 "Show Status Bar", ICON_MD_HORIZONTAL_RULE,
205 [this]() {
206 if (user_settings_) {
210 if (status_bar_) {
213 }
214 }
215 },
216 nullptr, nullptr,
217 [this]() {
219 })
220 .Separator()
221 .Item("Display Settings", ICON_MD_DISPLAY_SETTINGS,
222 [this]() { OnShowDisplaySettings(); })
223 .Item("Welcome Screen", ICON_MD_HOME,
224 [this]() { OnShowWelcomeScreen(); });
225}
226
228 const auto layout_enabled = [this]() {
229 return HasCurrentEditor();
230 };
231
233 .Item(
234 "Profile: Code", ICON_MD_CODE,
235 [this]() {
236 if (editor_manager_) {
238 }
239 },
240 nullptr, layout_enabled)
241 .Item(
242 "Profile: Debug", ICON_MD_BUG_REPORT,
243 [this]() {
244 if (editor_manager_) {
246 }
247 },
248 nullptr, layout_enabled)
249 .Item(
250 "Profile: Mapping", ICON_MD_MAP,
251 [this]() {
252 if (editor_manager_) {
254 }
255 },
256 nullptr, layout_enabled)
257 .Item(
258 "Profile: Chat + Agent", ICON_MD_SMART_TOY,
259 [this]() {
260 if (editor_manager_) {
262 }
263 },
264 nullptr, layout_enabled)
265 .Separator()
266 .Item(
267 "Developer", ICON_MD_DEVELOPER_MODE,
268 [this]() { OnLoadDeveloperLayout(); }, nullptr, layout_enabled)
269 .Item(
270 "Designer", ICON_MD_DESIGN_SERVICES,
271 [this]() { OnLoadDesignerLayout(); }, nullptr, layout_enabled)
272 .Item(
273 "Modder", ICON_MD_BUILD, [this]() { OnLoadModderLayout(); }, nullptr,
274 layout_enabled)
275 .Separator()
276 .Item(
277 "Reset Current Editor", ICON_MD_REFRESH,
278 [this]() {
279 if (editor_manager_) {
281 }
282 },
283 nullptr, layout_enabled)
284 .EndMenu();
285}
286
288 // Use CustomMenu to integrate dynamic panel content with the menu builder
289 menu_builder_.CustomMenu("Panels", [this]() { AddPanelsMenuItems(); });
290}
291
293 if (!panel_manager_) {
294 return;
295 }
296
297 const size_t session_id = session_coordinator_.GetActiveSessionIndex();
298 std::string active_category = panel_manager_->GetActiveCategory();
299 auto all_categories = panel_manager_->GetAllCategories(session_id);
300
301 if (all_categories.empty()) {
302 ImGui::TextDisabled("No panels available");
303 return;
304 }
305
306 // Panel Browser action at top
307 if (ImGui::MenuItem(absl::StrFormat("%s Panel Browser", ICON_MD_APPS).c_str(),
310 }
311 if (ImGui::MenuItem(
312 absl::StrFormat("%s Show All Panels", ICON_MD_VISIBILITY).c_str())) {
314 }
315 if (ImGui::MenuItem(
316 absl::StrFormat("%s Hide All Panels", ICON_MD_VISIBILITY_OFF)
317 .c_str())) {
319 }
320 ImGui::Separator();
321
322 // Show all categories as direct submenus (no nested "All Categories" wrapper)
323 for (const auto& category : all_categories) {
324 // Mark active category with icon
325 std::string label = category;
326 if (category == active_category) {
327 label = absl::StrFormat("%s %s", ICON_MD_FOLDER_OPEN, category);
328 } else {
329 label = absl::StrFormat("%s %s", ICON_MD_FOLDER, category);
330 }
331
332 if (ImGui::BeginMenu(label.c_str())) {
333 auto cards = panel_manager_->GetPanelsInCategory(session_id, category);
334
335 if (cards.empty()) {
336 ImGui::TextDisabled("No panels in this category");
337 } else {
338 if (ImGui::MenuItem(
339 absl::StrFormat("%s Show Category", ICON_MD_VISIBILITY)
340 .c_str())) {
341 panel_manager_->ShowAllPanelsInCategory(session_id, category);
342 }
343 if (ImGui::MenuItem(
344 absl::StrFormat("%s Hide Category", ICON_MD_VISIBILITY_OFF)
345 .c_str())) {
346 panel_manager_->HideAllPanelsInCategory(session_id, category);
347 }
348 ImGui::Separator();
349
350 for (const auto& card : cards) {
351 bool is_visible =
352 panel_manager_->IsPanelVisible(session_id, card.card_id);
353 const char* shortcut =
354 card.shortcut_hint.empty() ? nullptr : card.shortcut_hint.c_str();
355
356 // Show icon for visible panels
357 std::string item_label =
358 is_visible
359 ? absl::StrFormat("%s %s", ICON_MD_CHECK_BOX,
360 card.display_name)
361 : absl::StrFormat("%s %s", ICON_MD_CHECK_BOX_OUTLINE_BLANK,
362 card.display_name);
363
364 if (ImGui::MenuItem(item_label.c_str(), shortcut)) {
365 panel_manager_->TogglePanel(session_id, card.card_id);
366 }
367 }
368 }
369 ImGui::EndMenu();
370 }
371 }
372}
373
379
383
387
389
390#ifdef YAZE_ENABLE_TESTING
392#endif
393
394 // ImGui Debug (moved from Debug menu)
396 .Item("ImGui Demo", ICON_MD_HELP, [this]() { OnShowImGuiDemo(); })
397 .Item("ImGui Metrics", ICON_MD_ANALYTICS,
398 [this]() { OnShowImGuiMetrics(); })
399 .EndMenu()
400 .Separator();
401
402#ifdef YAZE_WITH_GRPC
403 AddCollaborationMenuItems();
404#endif
405}
406
408 // Search & Navigation
410 .Item(
411 "Global Search", ICON_MD_SEARCH, [this]() { OnShowGlobalSearch(); },
413 .Item(
414 "Command Palette", ICON_MD_SEARCH,
415 [this]() { OnShowCommandPalette(); }, SHORTCUT_CTRL_SHIFT(P))
416 .Item(
417 "Panel Finder", ICON_MD_DASHBOARD, [this]() { OnShowPanelFinder(); },
418 SHORTCUT_CTRL(P))
419 .Item("Resource Label Manager", ICON_MD_LABEL,
420 [this]() { OnShowResourceLabelManager(); });
421}
422
424 // ROM Analysis (moved from Debug menu)
426 .Item(
427 "ROM Information", ICON_MD_INFO, [this]() { OnShowRomInfo(); },
428 nullptr, [this]() { return HasActiveRom(); })
429 .Item(
430 "Data Integrity Check", ICON_MD_ANALYTICS,
431 [this]() { OnRunDataIntegrityCheck(); }, nullptr,
432 [this]() { return HasActiveRom(); })
433 .Item(
434 "Test Save/Load", ICON_MD_SAVE_ALT, [this]() { OnTestSaveLoad(); },
435 nullptr, [this]() { return HasActiveRom(); })
436 .EndMenu();
437
438 // ZSCustomOverworld (moved from Debug menu)
439 menu_builder_.BeginSubMenu("ZSCustomOverworld", ICON_MD_CODE)
440 .Item(
441 "Check ROM Version", ICON_MD_INFO, [this]() { OnCheckRomVersion(); },
442 nullptr, [this]() { return HasActiveRom(); })
443 .Item(
444 "Upgrade ROM", ICON_MD_UPGRADE, [this]() { OnUpgradeRom(); }, nullptr,
445 [this]() { return HasActiveRom(); })
446 .Item("Toggle Custom Loading", ICON_MD_SETTINGS,
447 [this]() { OnToggleCustomLoading(); })
448 .EndMenu();
449}
450
452 // Asar Integration (moved from Debug menu)
453 menu_builder_.BeginSubMenu("Asar Integration", ICON_MD_BUILD)
454 .Item("Asar Status", ICON_MD_INFO,
456 .Item(
457 "Toggle ASM Patch", ICON_MD_CODE, [this]() { OnToggleAsarPatch(); },
458 nullptr, [this]() { return HasActiveRom(); })
459 .Item("Load ASM File", ICON_MD_FOLDER_OPEN, [this]() { OnLoadAsmFile(); })
460 .EndMenu();
461}
462
464 // Development Tools (moved from Debug menu)
466 .Item("Memory Editor", ICON_MD_MEMORY, [this]() { OnShowMemoryEditor(); })
467 .Item("Assembly Editor", ICON_MD_CODE,
468 [this]() { OnShowAssemblyEditor(); })
469 .Item("Feature Flags", ICON_MD_FLAG,
471 .Item("Performance Dashboard", ICON_MD_SPEED,
472 [this]() { OnShowPerformanceDashboard(); })
473#ifdef YAZE_BUILD_AGENT_UI
474 .Item("Agent Workspace", ICON_MD_SMART_TOY, [this]() { OnShowAIAgent(); })
475#endif
476#ifdef YAZE_WITH_GRPC
477 .Item("Agent Proposals", ICON_MD_PREVIEW,
478 [this]() { OnShowProposalDrawer(); })
479#endif
480 .EndMenu();
481}
482
484 // Testing (moved from Debug menu)
486#ifdef YAZE_ENABLE_TESTING
488 .Item(
489 "Test Dashboard", ICON_MD_DASHBOARD,
490 [this]() { OnShowTestDashboard(); }, SHORTCUT_CTRL(T))
491 .Item("Run All Tests", ICON_MD_PLAY_ARROW, [this]() { OnRunAllTests(); })
492 .Item("Run Unit Tests", ICON_MD_CHECK_BOX, [this]() { OnRunUnitTests(); })
493 .Item("Run Integration Tests", ICON_MD_INTEGRATION_INSTRUCTIONS,
494 [this]() { OnRunIntegrationTests(); })
495 .Item("Run E2E Tests", ICON_MD_VISIBILITY, [this]() { OnRunE2ETests(); });
496#else
498 "Testing support disabled (YAZE_ENABLE_TESTING=OFF)", ICON_MD_INFO);
499#endif
501}
502
503#ifdef YAZE_WITH_GRPC
504void MenuOrchestrator::AddCollaborationMenuItems() {
505 // Collaboration (GRPC builds only)
507 .Item("Start Collaboration Session", ICON_MD_PLAY_CIRCLE,
508 [this]() { OnStartCollaboration(); })
509 .Item("Join Collaboration Session", ICON_MD_GROUP_ADD,
510 [this]() { OnJoinCollaboration(); })
511 .Item("Network Status", ICON_MD_CLOUD,
512 [this]() { OnShowNetworkStatus(); })
513 .EndMenu();
514}
515#endif
516
522
524 // Sessions Submenu
526 .Item(
527 "New Session", ICON_MD_ADD, [this]() { OnCreateNewSession(); },
529 .Item(
530 "Duplicate Session", ICON_MD_CONTENT_COPY,
531 [this]() { OnDuplicateCurrentSession(); }, nullptr,
532 [this]() { return HasActiveRom(); })
533 .Item(
534 "Close Session", ICON_MD_CLOSE, [this]() { OnCloseCurrentSession(); },
535 SHORTCUT_CTRL_SHIFT(W), [this]() { return HasMultipleSessions(); })
536 .Separator()
537 .Item(
538 "Session Switcher", ICON_MD_SWITCH_ACCOUNT,
539 [this]() { OnShowSessionSwitcher(); }, SHORTCUT_CTRL(Tab),
540 [this]() { return HasMultipleSessions(); })
541 .Item("Session Manager", ICON_MD_VIEW_LIST,
542 [this]() { OnShowSessionManager(); })
543 .EndMenu()
544 .Separator();
545
546 // Layout Management
547 const auto layout_actions_enabled = [this]() {
548 return HasCurrentEditor();
549 };
550
552 .Item(
553 "Save Layout", ICON_MD_SAVE, [this]() { OnSaveWorkspaceLayout(); },
555 .Item(
556 "Load Layout", ICON_MD_FOLDER_OPEN,
557 [this]() { OnLoadWorkspaceLayout(); }, SHORTCUT_CTRL_SHIFT(O))
558 .Item("Reset Layout", ICON_MD_RESET_TV,
559 [this]() { OnResetWorkspaceLayout(); })
560 .BeginSubMenu("Layout Presets", ICON_MD_VIEW_QUILT)
561 .Item(
562 "Reset Active Editor Layout", ICON_MD_REFRESH,
563 [this]() {
564 if (editor_manager_) {
566 }
567 },
568 nullptr, layout_actions_enabled)
569 .Separator()
570 .Item(
571 "Profile: Code", ICON_MD_CODE,
572 [this]() {
573 if (editor_manager_) {
575 }
576 },
577 nullptr, layout_actions_enabled)
578 .Item(
579 "Profile: Debug", ICON_MD_BUG_REPORT,
580 [this]() {
581 if (editor_manager_) {
583 }
584 },
585 nullptr, layout_actions_enabled)
586 .Item(
587 "Profile: Mapping", ICON_MD_MAP,
588 [this]() {
589 if (editor_manager_) {
591 }
592 },
593 nullptr, layout_actions_enabled)
594 .Item(
595 "Profile: Chat + Agent", ICON_MD_SMART_TOY,
596 [this]() {
597 if (editor_manager_) {
599 }
600 },
601 nullptr, layout_actions_enabled)
602 .Separator()
603 .Item(
604 "Capture Session Snapshot", ICON_MD_BOOKMARK_ADD,
605 [this]() {
606 if (editor_manager_) {
608 }
609 },
610 nullptr, layout_actions_enabled)
611 .Item(
612 "Restore Session Snapshot", ICON_MD_RESTORE,
613 [this]() {
614 if (editor_manager_) {
616 }
617 },
618 nullptr, layout_actions_enabled)
619 .Item(
620 "Clear Session Snapshot", ICON_MD_BOOKMARK_REMOVE,
621 [this]() {
622 if (editor_manager_) {
624 }
625 },
626 nullptr, layout_actions_enabled)
627 .Separator()
628 .Item(
629 "Minimal", ICON_MD_VIEW_COMPACT,
630 [this]() {
631 if (editor_manager_) {
633 }
634 },
635 nullptr, layout_actions_enabled)
636 .Item(
637 "Developer", ICON_MD_DEVELOPER_MODE,
638 [this]() { OnLoadDeveloperLayout(); }, nullptr,
639 layout_actions_enabled)
640 .Item(
641 "Designer", ICON_MD_DESIGN_SERVICES,
642 [this]() { OnLoadDesignerLayout(); }, nullptr, layout_actions_enabled)
643 .Item(
644 "Modder", ICON_MD_BUILD, [this]() { OnLoadModderLayout(); }, nullptr,
645 layout_actions_enabled)
646 .Item(
647 "Overworld Expert", ICON_MD_MAP,
648 [this]() {
649 if (editor_manager_) {
650 editor_manager_->ApplyLayoutPreset("Overworld Expert");
651 }
652 },
653 nullptr, layout_actions_enabled)
654 .Item(
655 "Dungeon Expert", ICON_MD_CASTLE,
656 [this]() {
657 if (editor_manager_) {
658 editor_manager_->ApplyLayoutPreset("Dungeon Expert");
659 }
660 },
661 nullptr, layout_actions_enabled)
662 .Item(
663 "Testing", ICON_MD_SCIENCE,
664 [this]() {
665 if (editor_manager_) {
667 }
668 },
669 nullptr, layout_actions_enabled)
670 .Item(
671 "Audio", ICON_MD_MUSIC_NOTE,
672 [this]() {
673 if (editor_manager_) {
675 }
676 },
677 nullptr, layout_actions_enabled)
678 .Separator()
679 .Item("Manage Presets...", ICON_MD_TUNE,
680 [this]() { OnShowLayoutPresets(); })
681 .EndMenu()
682 .Separator();
683
684 // Window Visibility
686 .Item("Show All Windows", ICON_MD_VISIBILITY,
687 [this]() { OnShowAllWindows(); })
688 .Item("Hide All Windows", ICON_MD_VISIBILITY_OFF,
689 [this]() { OnHideAllWindows(); })
690 .Separator();
691
692 // Panel Browser (requires ROM) - Panels are accessible via the sidebar
694 .Item(
695 "Panel Browser", ICON_MD_DASHBOARD,
696 [this]() { OnShowPanelBrowser(); }, SHORTCUT_CTRL_SHIFT(B),
697 [this]() { return HasActiveRom(); })
698 .Separator();
699
700 // Note: Panel toggle buttons are on the right side of the menu bar
701}
702
708
710 // Note: Asar Integration moved to Tools menu to reduce redundancy
712 .Item("Getting Started", ICON_MD_PLAY_ARROW,
713 [this]() { OnShowGettingStarted(); })
714 .Item("Keyboard Shortcuts", ICON_MD_KEYBOARD,
715 [this]() { OnShowSettings(); })
716 .Item("Build Instructions", ICON_MD_BUILD,
717 [this]() { OnShowBuildInstructions(); })
718 .Item("CLI Usage", ICON_MD_TERMINAL, [this]() { OnShowCLIUsage(); })
719 .Separator()
720 .Item("Supported Features", ICON_MD_CHECK_CIRCLE,
721 [this]() { OnShowSupportedFeatures(); })
722 .Item("What's New", ICON_MD_NEW_RELEASES, [this]() { OnShowWhatsNew(); })
723 .Separator()
724 .Item("Troubleshooting", ICON_MD_BUILD_CIRCLE,
725 [this]() { OnShowTroubleshooting(); })
726 .Item("Contributing", ICON_MD_VOLUNTEER_ACTIVISM,
727 [this]() { OnShowContributing(); })
728 .Separator()
729 .Item("About", ICON_MD_INFO, [this]() { OnShowAbout(); }, "F1");
730}
731
732// Menu state management
736
740
741// Menu item callbacks - delegate to appropriate managers
743 // Delegate to EditorManager's LoadRom which handles session management
744 if (editor_manager_) {
745 auto status = editor_manager_->LoadRom();
746 if (!status.ok()) {
748 absl::StrFormat("Failed to load ROM: %s", status.message()),
750 }
751 }
752}
753
755 // Delegate to EditorManager's SaveRom which handles editor data saving
756 if (editor_manager_) {
757 auto status = editor_manager_->SaveRom();
758 if (!status.ok()) {
759 if (absl::IsCancelled(status)) {
760 return;
761 }
763 absl::StrFormat("Failed to save ROM: %s", status.message()),
765 } else {
766 toast_manager_.Show("ROM saved successfully", ToastType::kSuccess);
767 }
768 }
769}
770
774
776 // Delegate to EditorManager which handles the full project creation flow
777 if (editor_manager_) {
778 auto status = editor_manager_->CreateNewProject();
779 if (!status.ok()) {
781 absl::StrFormat("Failed to create project: %s", status.message()),
783 }
784 }
785}
786
788 // Delegate to EditorManager which handles ROM loading and session creation
789 if (editor_manager_) {
790 auto status = editor_manager_->OpenProject();
791 if (!status.ok()) {
793 absl::StrFormat("Failed to open project: %s", status.message()),
795 }
796 }
797}
798
800 // Delegate to EditorManager which updates project with current state
801 if (editor_manager_) {
802 auto status = editor_manager_->SaveProject();
803 if (!status.ok()) {
805 absl::StrFormat("Failed to save project: %s", status.message()),
807 } else {
808 toast_manager_.Show("Project saved successfully", ToastType::kSuccess);
809 }
810 }
811}
812
814 // Delegate to EditorManager
815 if (editor_manager_) {
816 auto status = editor_manager_->SaveProjectAs();
817 if (!status.ok()) {
819 absl::StrFormat("Failed to save project as: %s", status.message()),
821 }
822 }
823}
824
826 // Show project management panel in right sidebar
827 if (editor_manager_) {
829 }
830}
831
833 // Open the project file editor with the current project file
834 if (editor_manager_) {
836 }
837}
838
839// Edit menu actions - delegate to current editor
841 if (editor_manager_) {
842 auto* current_editor = editor_manager_->GetCurrentEditor();
843 if (current_editor) {
844 // Capture description before undo moves the action to the redo stack
845 std::string desc = current_editor->GetUndoDescription();
846 auto status = current_editor->Undo();
847 if (status.ok()) {
848 if (!desc.empty()) {
849 toast_manager_.Show(absl::StrFormat("Undid: %s", desc),
850 ToastType::kInfo, 2.0f);
851 }
852 } else {
854 absl::StrFormat("Undo failed: %s", status.message()),
856 }
857 }
858 }
859}
860
862 if (editor_manager_) {
863 auto* current_editor = editor_manager_->GetCurrentEditor();
864 if (current_editor) {
865 // Capture description before redo moves the action to the undo stack
866 std::string desc = current_editor->GetRedoDescription();
867 auto status = current_editor->Redo();
868 if (status.ok()) {
869 if (!desc.empty()) {
870 toast_manager_.Show(absl::StrFormat("Redid: %s", desc),
871 ToastType::kInfo, 2.0f);
872 }
873 } else {
875 absl::StrFormat("Redo failed: %s", status.message()),
877 }
878 }
879 }
880}
881
883 if (editor_manager_) {
884 auto* current_editor = editor_manager_->GetCurrentEditor();
885 if (current_editor) {
886 auto status = current_editor->Cut();
887 if (!status.ok()) {
888 toast_manager_.Show(absl::StrFormat("Cut failed: %s", status.message()),
890 }
891 }
892 }
893}
894
896 if (editor_manager_) {
897 auto* current_editor = editor_manager_->GetCurrentEditor();
898 if (current_editor) {
899 auto status = current_editor->Copy();
900 if (!status.ok()) {
902 absl::StrFormat("Copy failed: %s", status.message()),
904 }
905 }
906 }
907}
908
910 if (editor_manager_) {
911 auto* current_editor = editor_manager_->GetCurrentEditor();
912 if (current_editor) {
913 auto status = current_editor->Paste();
914 if (!status.ok()) {
916 absl::StrFormat("Paste failed: %s", status.message()),
918 }
919 }
920 }
921}
922
924 if (editor_manager_) {
925 auto* current_editor = editor_manager_->GetCurrentEditor();
926 if (current_editor) {
927 auto status = current_editor->Find();
928 if (!status.ok()) {
930 absl::StrFormat("Find failed: %s", status.message()),
932 }
933 }
934 }
935}
936
937// Editor-specific menu actions
939 // Delegate to EditorManager which manages editor switching
940 if (editor_manager_) {
941 editor_manager_->SwitchToEditor(editor_type);
942 }
943}
944
946 // Delegate to UICoordinator for editor selection dialog display
947 if (editor_manager_) {
948 if (auto* ui = editor_manager_->ui_coordinator()) {
949 ui->ShowEditorSelection();
950 }
951 }
952}
953
957
959 // Show hex editor card via EditorPanelManager
960 if (editor_manager_) {
962 editor_manager_->GetCurrentSessionId(), "Hex Editor");
963 }
964}
965
967 if (editor_manager_) {
968 if (auto* ui = editor_manager_->ui_coordinator()) {
969 ui->SetPanelBrowserVisible(true);
970 }
971 }
972}
973
975 if (editor_manager_) {
976 if (auto* ui = editor_manager_->ui_coordinator()) {
977 ui->ShowPanelFinder();
978 }
979 }
980}
981
983 if (editor_manager_) {
984 if (auto* ui = editor_manager_->ui_coordinator()) {
985 ui->SetWelcomeScreenVisible(true);
986 }
987 }
988}
989
990#ifdef YAZE_BUILD_AGENT_UI
991void MenuOrchestrator::OnShowAIAgent() {
992 if (editor_manager_) {
993 if (auto* ui = editor_manager_->ui_coordinator()) {
994 ui->SetAIAgentVisible(true);
995 }
996 }
997}
998
999void MenuOrchestrator::OnShowProposalDrawer() {
1000 if (editor_manager_) {
1001 if (auto* ui = editor_manager_->ui_coordinator()) {
1002 ui->SetProposalDrawerVisible(true);
1003 }
1004 }
1005}
1006#endif
1007
1008// Session management menu actions
1012
1016
1020
1022 // Delegate to UICoordinator for session switcher UI
1023 if (editor_manager_) {
1024 if (auto* ui = editor_manager_->ui_coordinator()) {
1025 ui->ShowSessionSwitcher();
1026 }
1027 }
1028}
1029
1033
1034// Window management menu actions
1036 // Delegate to EditorManager
1037 if (editor_manager_) {
1038 if (auto* ui = editor_manager_->ui_coordinator()) {
1039 ui->ShowAllWindows();
1040 }
1041 }
1042}
1043
1045 // Delegate to EditorManager
1046 if (editor_manager_) {
1048 }
1049}
1050
1052 // Queue as deferred action to avoid modifying ImGui state during menu rendering
1053 if (editor_manager_) {
1056 toast_manager_.Show("Layout reset to default", ToastType::kInfo);
1057 });
1058 }
1059}
1060
1062 // Delegate to EditorManager
1063 if (editor_manager_) {
1065 }
1066}
1067
1069 // Delegate to EditorManager
1070 if (editor_manager_) {
1072 }
1073}
1074
1078
1084
1090
1096
1097// Tool menu actions
1099 if (editor_manager_) {
1100 if (auto* ui = editor_manager_->ui_coordinator()) {
1101 ui->ShowGlobalSearch();
1102 }
1103 }
1104}
1105
1107 if (editor_manager_) {
1108 if (auto* ui = editor_manager_->ui_coordinator()) {
1109 ui->ShowCommandPalette();
1110 }
1111 }
1112}
1113
1115 if (editor_manager_) {
1116 if (auto* ui = editor_manager_->ui_coordinator()) {
1117 ui->SetPerformanceDashboardVisible(true);
1118 }
1119 }
1120}
1121
1127
1133
1140
1142 if (editor_manager_) {
1143 if (auto* ui = editor_manager_->ui_coordinator()) {
1144 ui->SetResourceLabelManagerVisible(true);
1145 }
1146 }
1147}
1148
1149#ifdef YAZE_ENABLE_TESTING
1150void MenuOrchestrator::OnShowTestDashboard() {
1151 if (editor_manager_) {
1152 editor_manager_->ShowTestDashboard();
1153 }
1154}
1155
1156void MenuOrchestrator::OnRunAllTests() {
1157 toast_manager_.Show("Running all tests...", ToastType::kInfo);
1158 // TODO: Implement test runner integration
1159}
1160
1161void MenuOrchestrator::OnRunUnitTests() {
1162 toast_manager_.Show("Running unit tests...", ToastType::kInfo);
1163 // TODO: Implement unit test runner
1164}
1165
1166void MenuOrchestrator::OnRunIntegrationTests() {
1167 toast_manager_.Show("Running integration tests...", ToastType::kInfo);
1168 // TODO: Implement integration test runner
1169}
1170
1171void MenuOrchestrator::OnRunE2ETests() {
1173 "E2E runner is not wired in-app yet. Use scripts/agents/run-tests.sh or "
1174 "z3ed test-run.",
1176}
1177#endif
1178
1179#ifdef YAZE_WITH_GRPC
1180void MenuOrchestrator::OnStartCollaboration() {
1182 "Collaboration session start is not wired yet. Run yaze-server and use "
1183 "the web client for live sync.",
1185}
1186
1187void MenuOrchestrator::OnJoinCollaboration() {
1189 "Join collaboration is not wired yet. Use the web client + yaze-server.",
1191}
1192
1193void MenuOrchestrator::OnShowNetworkStatus() {
1194 toast_manager_.Show("Network status panel is not implemented yet.",
1196}
1197#endif
1198
1199// Help menu actions
1203
1207
1211
1215
1219
1223
1227
1231
1232// Additional File menu actions
1236
1238 if (editor_manager_) {
1240 if (status.ok()) {
1241 toast_manager_.Show("Backup created successfully", ToastType::kSuccess);
1242 } else {
1244 absl::StrFormat("Backup failed: %s", status.message()),
1246 }
1247 }
1248}
1249
1251 if (editor_manager_) {
1253 if (status.ok()) {
1254 toast_manager_.Show("ROM validation passed", ToastType::kSuccess);
1255 } else {
1257 absl::StrFormat("ROM validation failed: %s", status.message()),
1259 }
1260 }
1261}
1262
1264 // Activate settings editor
1265 if (editor_manager_) {
1267 }
1268}
1269
1271 if (editor_manager_) {
1273 }
1274}
1275
1276// Menu item validation helpers
1278 auto* rom = editor_manager_->GetCurrentRom();
1279 return rom ? rom_manager_.IsRomLoaded(rom) : false;
1280}
1281
1285
1287 auto* rom = editor_manager_->GetCurrentRom();
1288 return rom ? rom_manager_.IsRomLoaded(rom) : false;
1289}
1290
1294
1296 // Check if EditorManager has a project with a valid filepath
1297 // This is separate from HasActiveProject which checks ProjectManager
1298 const auto* project =
1300 return project && !project->filepath.empty();
1301}
1302
1306
1310
1311// Menu item text generation
1313 auto* rom = editor_manager_->GetCurrentRom();
1314 return rom ? rom_manager_.GetRomFilename(rom) : "";
1315}
1316
1319}
1320
1322 // TODO: Get current editor name
1323 return "Unknown Editor";
1324}
1325
1326// Shortcut key management
1328 const std::string& action) const {
1329 // TODO: Implement shortcut mapping
1330 return "";
1331}
1332
1334 // TODO: Register global keyboard shortcuts
1335}
1336
1337// ============================================================================
1338// Debug Menu Actions
1339// ============================================================================
1340
1342#ifdef YAZE_ENABLE_TESTING
1343 if (!editor_manager_)
1344 return;
1345 auto* rom = editor_manager_->GetCurrentRom();
1346 if (!rom || !rom->is_loaded())
1347 return;
1348
1349 toast_manager_.Show("Running ROM integrity tests...", ToastType::kInfo);
1350 // This would integrate with the test system in master
1351 // For now, just show a placeholder
1352 toast_manager_.Show("Data integrity check completed", ToastType::kSuccess,
1353 3.0f);
1354#else
1355 toast_manager_.Show("Testing not enabled in this build", ToastType::kWarning);
1356#endif
1357}
1358
1360#ifdef YAZE_ENABLE_TESTING
1361 if (!editor_manager_)
1362 return;
1363 auto* rom = editor_manager_->GetCurrentRom();
1364 if (!rom || !rom->is_loaded())
1365 return;
1366
1367 toast_manager_.Show("Running ROM save/load tests...", ToastType::kInfo);
1368 // This would integrate with the test system in master
1369 toast_manager_.Show("Save/load test completed", ToastType::kSuccess, 3.0f);
1370#else
1371 toast_manager_.Show("Testing not enabled in this build", ToastType::kWarning);
1372#endif
1373}
1374
1376 if (!editor_manager_)
1377 return;
1378 auto* rom = editor_manager_->GetCurrentRom();
1379 if (!rom || !rom->is_loaded())
1380 return;
1381
1382 // Check ZSCustomOverworld version
1383 uint8_t version = (*rom)[zelda3::OverworldCustomASMHasBeenApplied];
1384 std::string version_str =
1385 (version == 0xFF) ? "Vanilla" : absl::StrFormat("v%d", version);
1386
1388 absl::StrFormat("ROM: %s | ZSCustomOverworld: %s", rom->title().c_str(),
1389 version_str.c_str()),
1390 ToastType::kInfo, 5.0f);
1391}
1392
1394 if (!editor_manager_)
1395 return;
1396 auto* rom = editor_manager_->GetCurrentRom();
1397 if (!rom || !rom->is_loaded())
1398 return;
1399
1400 toast_manager_.Show("Use Overworld Editor to upgrade ROM version",
1401 ToastType::kInfo, 4.0f);
1402}
1403
1405 auto& flags = core::FeatureFlags::get();
1406 flags.overworld.kLoadCustomOverworld = !flags.overworld.kLoadCustomOverworld;
1407
1409 absl::StrFormat(
1410 "Custom Overworld Loading: %s",
1411 flags.overworld.kLoadCustomOverworld ? "Enabled" : "Disabled"),
1413}
1414
1416 if (!editor_manager_)
1417 return;
1418 auto* rom = editor_manager_->GetCurrentRom();
1419 if (!rom || !rom->is_loaded())
1420 return;
1421
1422 auto& flags = core::FeatureFlags::get();
1423 flags.overworld.kApplyZSCustomOverworldASM =
1424 !flags.overworld.kApplyZSCustomOverworldASM;
1425
1427 absl::StrFormat(
1428 "ZSCustomOverworld ASM Application: %s",
1429 flags.overworld.kApplyZSCustomOverworldASM ? "Enabled" : "Disabled"),
1431}
1432
1434 toast_manager_.Show("ASM file loading not yet implemented",
1436}
1437
1443
1444} // namespace editor
1445} // namespace yaze
bool is_loaded() const
Definition rom.h:132
auto title() const
Definition rom.h:137
static Flags & get()
Definition features.h:118
The EditorManager controls the main editor window and manages the various editor classes.
void SwitchToEditor(EditorType editor_type, bool force_visible=false, bool from_dialog=false) override
Rom * GetCurrentRom() const override
UICoordinator * ui_coordinator()
void ShowProjectManagement()
Injects dependencies into all editors within an EditorSet.
absl::Status CreateNewProject(const std::string &template_name="Basic ROM Hack")
void ApplyLayoutPreset(const std::string &preset_name)
void RestoreTemporaryLayoutSnapshot(bool clear_after_restore=false)
auto GetCurrentEditor() const -> Editor *
bool ApplyLayoutProfile(const std::string &profile_id)
absl::Status LoadRom()
Load a ROM file into a new or existing session.
project::YazeProject * GetCurrentProject()
void QueueDeferredAction(std::function< void()> action)
Manages editor types, categories, and lifecycle.
virtual absl::Status Cut()=0
virtual absl::Status Copy()=0
virtual absl::Status Redo()=0
virtual std::string GetRedoDescription() const
Definition editor.h:273
virtual absl::Status Find()=0
virtual absl::Status Paste()=0
virtual absl::Status Undo()=0
virtual std::string GetUndoDescription() const
Definition editor.h:270
Fluent interface for building ImGui menus with icons.
MenuBuilder & Item(const char *label, const char *icon, Callback callback, const char *shortcut=nullptr, EnabledCheck enabled=nullptr, EnabledCheck checked=nullptr)
Add a menu item.
MenuBuilder & CustomMenu(const char *label, Callback draw_callback)
Add a custom menu with a callback for drawing dynamic content.
void Draw()
Draw the menu bar (call in main menu bar)
void Clear()
Clear all menus.
MenuBuilder & BeginMenu(const char *label, const char *icon=nullptr)
Begin a top-level menu.
MenuBuilder & Separator()
Add a separator.
MenuBuilder & EndMenu()
End the current menu/submenu.
MenuBuilder & BeginSubMenu(const char *label, const char *icon=nullptr, EnabledCheck enabled=nullptr)
Begin a submenu.
MenuBuilder & DisabledItem(const char *label, const char *icon=nullptr)
Add a disabled item (grayed out)
void OnSwitchToEditor(EditorType editor_type)
SessionCoordinator & session_coordinator_
MenuOrchestrator(EditorManager *editor_manager, MenuBuilder &menu_builder, RomFileManager &rom_manager, ProjectManager &project_manager, EditorRegistry &editor_registry, SessionCoordinator &session_coordinator, ToastManager &toast_manager, PopupManager &popup_manager)
std::string GetShortcutForAction(const std::string &action) const
std::vector< std::string > GetAllCategories(size_t session_id) const
bool TogglePanel(size_t session_id, const std::string &base_card_id)
void HideAllPanelsInSession(size_t session_id)
std::vector< PanelDescriptor > GetPanelsInCategory(size_t session_id, const std::string &category) const
bool ShowPanel(size_t session_id, const std::string &base_card_id)
std::string GetActiveCategory() const
bool IsPanelVisible(size_t session_id, const std::string &base_card_id) const
void ShowAllPanelsInCategory(size_t session_id, const std::string &category)
void HideAllPanelsInCategory(size_t session_id, const std::string &category)
void ShowAllPanelsInSession(size_t session_id)
void Show(const char *name)
Handles all project file operations with ROM-first workflow.
std::string GetProjectName() const
Handles all ROM file I/O operations.
absl::Status ValidateRom(Rom *rom)
std::string GetRomFilename(Rom *rom) const
absl::Status CreateBackup(Rom *rom)
bool IsRomLoaded(Rom *rom) const
High-level orchestrator for multi-session UI.
void SetEnabled(bool enabled)
Enable or disable the status bar.
Definition status_bar.h:53
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
#define ICON_MD_DEVELOPER_MODE
Definition icons.h:549
#define ICON_MD_FOLDER_OPEN
Definition icons.h:813
#define ICON_MD_CONTENT_CUT
Definition icons.h:466
#define ICON_MD_SAVE_ALT
Definition icons.h:1645
#define ICON_MD_VOLUNTEER_ACTIVISM
Definition icons.h:2112
#define ICON_MD_SETTINGS
Definition icons.h:1699
#define ICON_MD_FILE_OPEN
Definition icons.h:747
#define ICON_MD_CHECK_BOX
Definition icons.h:398
#define ICON_MD_EXIT_TO_APP
Definition icons.h:699
#define ICON_MD_VIEW_QUILT
Definition icons.h:2094
#define ICON_MD_APPS
Definition icons.h:168
#define ICON_MD_INFO
Definition icons.h:993
#define ICON_MD_MEMORY
Definition icons.h:1195
#define ICON_MD_STORAGE
Definition icons.h:1865
#define ICON_MD_UPGRADE
Definition icons.h:2047
#define ICON_MD_FOLDER_SPECIAL
Definition icons.h:815
#define ICON_MD_VIEW_LIST
Definition icons.h:2092
#define ICON_MD_SEARCH
Definition icons.h:1673
#define ICON_MD_NEW_RELEASES
Definition icons.h:1291
#define ICON_MD_PLAY_ARROW
Definition icons.h:1479
#define ICON_MD_SWAP_HORIZ
Definition icons.h:1896
#define ICON_MD_SAVE_AS
Definition icons.h:1646
#define ICON_MD_DESIGN_SERVICES
Definition icons.h:541
#define ICON_MD_INTEGRATION_INSTRUCTIONS
Definition icons.h:1008
#define ICON_MD_RESET_TV
Definition icons.h:1601
#define ICON_MD_TUNE
Definition icons.h:2022
#define ICON_MD_REFRESH
Definition icons.h:1572
#define ICON_MD_MAP
Definition icons.h:1173
#define ICON_MD_CODE
Definition icons.h:434
#define ICON_MD_LABEL
Definition icons.h:1053
#define ICON_MD_REDO
Definition icons.h:1570
#define ICON_MD_SWITCH_ACCOUNT
Definition icons.h:1913
#define ICON_MD_VISIBILITY
Definition icons.h:2101
#define ICON_MD_BUG_REPORT
Definition icons.h:327
#define ICON_MD_SPEED
Definition icons.h:1817
#define ICON_MD_CASTLE
Definition icons.h:380
#define ICON_MD_BUILD_CIRCLE
Definition icons.h:329
#define ICON_MD_MUSIC_NOTE
Definition icons.h:1264
#define ICON_MD_RESTORE
Definition icons.h:1605
#define ICON_MD_CONTENT_PASTE
Definition icons.h:467
#define ICON_MD_HOME
Definition icons.h:953
#define ICON_MD_VISIBILITY_OFF
Definition icons.h:2102
#define ICON_MD_DISPLAY_SETTINGS
Definition icons.h:587
#define ICON_MD_BOOKMARK_ADD
Definition icons.h:286
#define ICON_MD_VIEW_COMPACT
Definition icons.h:2085
#define ICON_MD_ADD
Definition icons.h:86
#define ICON_MD_KEYBOARD
Definition icons.h:1028
#define ICON_MD_SCIENCE
Definition icons.h:1656
#define ICON_MD_PLAY_CIRCLE
Definition icons.h:1480
#define ICON_MD_CHECK_CIRCLE
Definition icons.h:400
#define ICON_MD_TERMINAL
Definition icons.h:1951
#define ICON_MD_PREVIEW
Definition icons.h:1512
#define ICON_MD_FLAG
Definition icons.h:784
#define ICON_MD_DESCRIPTION
Definition icons.h:539
#define ICON_MD_BUILD
Definition icons.h:328
#define ICON_MD_HORIZONTAL_RULE
Definition icons.h:960
#define ICON_MD_CREATE_NEW_FOLDER
Definition icons.h:483
#define ICON_MD_DASHBOARD
Definition icons.h:517
#define ICON_MD_SAVE
Definition icons.h:1644
#define ICON_MD_TAB
Definition icons.h:1930
#define ICON_MD_PEOPLE
Definition icons.h:1401
#define ICON_MD_FOLDER
Definition icons.h:809
#define ICON_MD_BACKUP
Definition icons.h:231
#define ICON_MD_CONTENT_COPY
Definition icons.h:465
#define ICON_MD_CLOUD
Definition icons.h:423
#define ICON_MD_CLOSE
Definition icons.h:418
#define ICON_MD_ANALYTICS
Definition icons.h:154
#define ICON_MD_HELP
Definition icons.h:933
#define ICON_MD_CHECK_BOX_OUTLINE_BLANK
Definition icons.h:399
#define ICON_MD_VIEW_SIDEBAR
Definition icons.h:2095
#define ICON_MD_BOOKMARK_REMOVE
Definition icons.h:290
#define ICON_MD_UNDO
Definition icons.h:2039
#define ICON_MD_SMART_TOY
Definition icons.h:1781
#define ICON_MD_GROUP_ADD
Definition icons.h:899
#define SHORTCUT_CTRL_SHIFT(key)
#define SHORTCUT_CTRL(key)
constexpr const char * kRomInfo
constexpr const char * kLayoutPresets
constexpr const char * kSaveScope
constexpr const char * kAbout
constexpr const char * kSessionManager
constexpr const char * kTroubleshooting
constexpr const char * kRomBackups
constexpr const char * kWhatsNew
constexpr const char * kSupportedFeatures
constexpr const char * kSaveAs
constexpr const char * kDisplaySettings
constexpr const char * kCLIUsage
constexpr const char * kAsarIntegration
constexpr const char * kFeatureFlags
constexpr const char * kGettingStarted
constexpr const char * kContributing
constexpr const char * kBuildInstructions
constexpr int OverworldCustomASMHasBeenApplied
Definition common.h:89