refactor(editor): introduce MenuOrchestrator for menu management
- Added MenuOrchestrator class to handle menu construction and coordination, improving separation of concerns within the editor. - Refactored EditorManager to delegate menu-related tasks to MenuOrchestrator, enhancing maintainability and clarity. - Updated CMake configuration to include new source files for the MenuOrchestrator component. Benefits: - Streamlines menu management, leading to a more organized and efficient user experience. - Enhances the overall architecture by clearly defining roles for menu handling and editor operations.
This commit is contained in:
@@ -35,6 +35,7 @@ set(
|
||||
app/editor/system/command_palette.cc
|
||||
app/editor/system/editor_registry.cc
|
||||
app/editor/system/extension_manager.cc
|
||||
app/editor/system/menu_orchestrator.cc
|
||||
app/editor/system/popup_manager.cc
|
||||
app/editor/system/project_manager.cc
|
||||
app/editor/system/proposal_drawer.cc
|
||||
|
||||
@@ -133,6 +133,11 @@ EditorManager::EditorManager()
|
||||
// Initialize new delegated components
|
||||
session_coordinator_ = std::make_unique<SessionCoordinator>(
|
||||
static_cast<void*>(&sessions_), &card_registry_, &toast_manager_);
|
||||
|
||||
// Initialize MenuOrchestrator after SessionCoordinator is created
|
||||
menu_orchestrator_ = std::make_unique<MenuOrchestrator>(
|
||||
menu_builder_, rom_file_manager_, project_manager_, editor_registry_,
|
||||
*session_coordinator_, toast_manager_);
|
||||
}
|
||||
|
||||
EditorManager::~EditorManager() = default;
|
||||
@@ -1093,521 +1098,10 @@ void EditorManager::DrawContextSensitiveCardControl() {
|
||||
}
|
||||
|
||||
void EditorManager::BuildModernMenu() {
|
||||
menu_builder_.Clear();
|
||||
|
||||
// File Menu - enhanced with ROM features
|
||||
menu_builder_.BeginMenu("File")
|
||||
.Item(
|
||||
"Open ROM", ICON_MD_FILE_OPEN, [this]() { status_ = LoadRom(); },
|
||||
"Ctrl+O")
|
||||
.Item(
|
||||
"Save ROM", ICON_MD_SAVE, [this]() { status_ = SaveRom(); }, "Ctrl+S",
|
||||
[this]() { return current_rom_ && current_rom_->is_loaded(); })
|
||||
.Item(
|
||||
"Save As...", ICON_MD_SAVE_AS,
|
||||
[this]() { popup_manager_->Show("Save As.."); }, nullptr,
|
||||
[this]() { return current_rom_ && current_rom_->is_loaded(); })
|
||||
.Separator()
|
||||
.Item("New Project", ICON_MD_CREATE_NEW_FOLDER,
|
||||
[this]() { status_ = CreateNewProject(); })
|
||||
.Item("Open Project", ICON_MD_FOLDER_OPEN,
|
||||
[this]() { status_ = OpenProject(); })
|
||||
.Item(
|
||||
"Save Project", ICON_MD_SAVE, [this]() { status_ = SaveProject(); },
|
||||
nullptr, [this]() { return !current_project_.filepath.empty(); })
|
||||
.Item(
|
||||
"Save Project As...", ICON_MD_SAVE_AS,
|
||||
[this]() { status_ = SaveProjectAs(); }, nullptr,
|
||||
[this]() { return !current_project_.filepath.empty(); })
|
||||
.Separator()
|
||||
.Item(
|
||||
"ROM Information", ICON_MD_INFO,
|
||||
[this]() { popup_manager_->Show("ROM Info"); }, nullptr,
|
||||
[this]() { return current_rom_ && current_rom_->is_loaded(); })
|
||||
.Item(
|
||||
"Create Backup", ICON_MD_BACKUP,
|
||||
[this]() {
|
||||
if (current_rom_ && current_rom_->is_loaded()) {
|
||||
Rom::SaveSettings settings;
|
||||
settings.backup = true;
|
||||
settings.filename = current_rom_->filename();
|
||||
status_ = current_rom_->SaveToFile(settings);
|
||||
if (status_.ok()) {
|
||||
toast_manager_.Show("Backup created successfully",
|
||||
ToastType::kSuccess);
|
||||
}
|
||||
}
|
||||
},
|
||||
nullptr,
|
||||
[this]() { return current_rom_ && current_rom_->is_loaded(); })
|
||||
.Item(
|
||||
"Validate ROM", ICON_MD_CHECK_CIRCLE,
|
||||
[this]() {
|
||||
if (current_rom_ && current_rom_->is_loaded()) {
|
||||
auto result = current_project_.Validate();
|
||||
if (result.ok()) {
|
||||
toast_manager_.Show("ROM validation passed",
|
||||
ToastType::kSuccess);
|
||||
} else {
|
||||
toast_manager_.Show(
|
||||
"ROM validation failed: " + std::string(result.message()),
|
||||
ToastType::kError);
|
||||
}
|
||||
}
|
||||
},
|
||||
nullptr,
|
||||
[this]() { return current_rom_ && current_rom_->is_loaded(); })
|
||||
.Separator()
|
||||
.Item(
|
||||
"Settings", ICON_MD_SETTINGS,
|
||||
[this]() { current_editor_set_->settings_editor_.set_active(true); })
|
||||
.Separator()
|
||||
.Item(
|
||||
"Quit", ICON_MD_EXIT_TO_APP, [this]() { quit_ = true; }, "Ctrl+Q")
|
||||
.EndMenu();
|
||||
|
||||
// Edit Menu
|
||||
menu_builder_.BeginMenu("Edit")
|
||||
.Item(
|
||||
"Undo", ICON_MD_UNDO,
|
||||
[this]() {
|
||||
if (current_editor_)
|
||||
status_ = current_editor_->Undo();
|
||||
},
|
||||
"Ctrl+Z")
|
||||
.Item(
|
||||
"Redo", ICON_MD_REDO,
|
||||
[this]() {
|
||||
if (current_editor_)
|
||||
status_ = current_editor_->Redo();
|
||||
},
|
||||
"Ctrl+Y")
|
||||
.Separator()
|
||||
.Item(
|
||||
"Cut", ICON_MD_CONTENT_CUT,
|
||||
[this]() {
|
||||
if (current_editor_)
|
||||
status_ = current_editor_->Cut();
|
||||
},
|
||||
"Ctrl+X")
|
||||
.Item(
|
||||
"Copy", ICON_MD_CONTENT_COPY,
|
||||
[this]() {
|
||||
if (current_editor_)
|
||||
status_ = current_editor_->Copy();
|
||||
},
|
||||
"Ctrl+C")
|
||||
.Item(
|
||||
"Paste", ICON_MD_CONTENT_PASTE,
|
||||
[this]() {
|
||||
if (current_editor_)
|
||||
status_ = current_editor_->Paste();
|
||||
},
|
||||
"Ctrl+V")
|
||||
.Separator()
|
||||
.Item(
|
||||
"Find", ICON_MD_SEARCH,
|
||||
[this]() {
|
||||
if (current_editor_)
|
||||
status_ = current_editor_->Find();
|
||||
},
|
||||
"Ctrl+F")
|
||||
.Item(
|
||||
"Find in Files", ICON_MD_SEARCH,
|
||||
[this]() { show_global_search_ = true; }, "Ctrl+Shift+F")
|
||||
.EndMenu();
|
||||
|
||||
// View Menu - editors and cards
|
||||
menu_builder_.BeginMenu("View")
|
||||
.Item(
|
||||
"Editor Selection", ICON_MD_DASHBOARD,
|
||||
[this]() { show_editor_selection_ = true; }, "Ctrl+E")
|
||||
.Separator()
|
||||
.Item(
|
||||
"Overworld", ICON_MD_MAP,
|
||||
[this]() { SwitchToEditor(EditorType::kOverworld); }, "Ctrl+1")
|
||||
.Item(
|
||||
"Dungeon", ICON_MD_CASTLE,
|
||||
[this]() { SwitchToEditor(EditorType::kDungeon); }, "Ctrl+2")
|
||||
.Item(
|
||||
"Graphics", ICON_MD_IMAGE,
|
||||
[this]() { SwitchToEditor(EditorType::kGraphics); }, "Ctrl+3")
|
||||
.Item(
|
||||
"Sprites", ICON_MD_TOYS,
|
||||
[this]() { SwitchToEditor(EditorType::kSprite); }, "Ctrl+4")
|
||||
.Item(
|
||||
"Messages", ICON_MD_CHAT_BUBBLE,
|
||||
[this]() { SwitchToEditor(EditorType::kMessage); }, "Ctrl+5")
|
||||
.Item(
|
||||
"Music", ICON_MD_MUSIC_NOTE,
|
||||
[this]() { SwitchToEditor(EditorType::kMusic); }, "Ctrl+6")
|
||||
.Item(
|
||||
"Palettes", ICON_MD_PALETTE,
|
||||
[this]() { SwitchToEditor(EditorType::kPalette); }, "Ctrl+7")
|
||||
.Item(
|
||||
"Screens", ICON_MD_TV,
|
||||
[this]() { SwitchToEditor(EditorType::kScreen); }, "Ctrl+8")
|
||||
.Item(
|
||||
"Hex Editor", ICON_MD_DATA_ARRAY,
|
||||
[this]() {
|
||||
gui::EditorCardManager::Get().ShowCard("memory.hex_editor");
|
||||
},
|
||||
"Ctrl+0")
|
||||
#ifdef YAZE_WITH_GRPC
|
||||
.Item(
|
||||
"AI Agent", ICON_MD_SMART_TOY,
|
||||
[this]() { agent_editor_.set_active(true); }, "Ctrl+Shift+A")
|
||||
.Item(
|
||||
"Chat History", ICON_MD_CHAT,
|
||||
[this]() { agent_chat_history_popup_.Toggle(); }, "Ctrl+H")
|
||||
.Item(
|
||||
"Proposal Drawer", ICON_MD_PREVIEW,
|
||||
[this]() { proposal_drawer_.Toggle(); }, "Ctrl+P")
|
||||
#endif
|
||||
.Separator();
|
||||
menu_builder_.Item(
|
||||
"Card Browser", ICON_MD_DASHBOARD,
|
||||
[this]() { show_card_browser_ = true; }, "Ctrl+Shift+B")
|
||||
.Separator()
|
||||
.Item("Welcome Screen", ICON_MD_HOME,
|
||||
[this]() { show_welcome_screen_ = true; })
|
||||
.Item(
|
||||
"Command Palette", ICON_MD_TERMINAL,
|
||||
[this]() { show_command_palette_ = true; }, "Ctrl+Shift+P")
|
||||
.Item(
|
||||
"Emulator", ICON_MD_GAMEPAD, [this]() { show_emulator_ = true; },
|
||||
nullptr, nullptr, [this]() { return show_emulator_; })
|
||||
.EndMenu();
|
||||
|
||||
// Window Menu - layout and session management
|
||||
menu_builder_.BeginMenu("Window")
|
||||
.BeginSubMenu("Sessions", ICON_MD_TAB)
|
||||
.Item(
|
||||
"New Session", ICON_MD_ADD, [this]() { CreateNewSession(); },
|
||||
"Ctrl+Shift+N")
|
||||
.Item(
|
||||
"Duplicate Session", ICON_MD_CONTENT_COPY,
|
||||
[this]() { DuplicateCurrentSession(); }, nullptr,
|
||||
[this]() { return current_rom_ != nullptr; })
|
||||
.Item(
|
||||
"Close Session", ICON_MD_CLOSE, [this]() { CloseCurrentSession(); },
|
||||
"Ctrl+Shift+W", [this]() { return sessions_.size() > 1; })
|
||||
.Separator()
|
||||
.Item(
|
||||
"Session Switcher", ICON_MD_SWITCH_ACCOUNT,
|
||||
[this]() { show_session_switcher_ = true; }, "Ctrl+Tab",
|
||||
[this]() { return sessions_.size() > 1; })
|
||||
.Item("Session Manager", ICON_MD_VIEW_LIST,
|
||||
[this]() { show_session_manager_ = true; })
|
||||
.EndMenu()
|
||||
.Separator()
|
||||
.Item(
|
||||
"Save Layout", ICON_MD_SAVE, [this]() { SaveWorkspaceLayout(); },
|
||||
"Ctrl+Shift+S")
|
||||
.Item(
|
||||
"Load Layout", ICON_MD_FOLDER_OPEN,
|
||||
[this]() { LoadWorkspaceLayout(); }, "Ctrl+Shift+O")
|
||||
.Item("Reset Layout", ICON_MD_RESET_TV,
|
||||
[this]() { ResetWorkspaceLayout(); })
|
||||
.Item("Layout Presets", ICON_MD_BOOKMARK,
|
||||
[this]() { show_layout_presets_ = true; })
|
||||
.Separator()
|
||||
.Item("Show All Windows", ICON_MD_VISIBILITY,
|
||||
[this]() { ShowAllWindows(); })
|
||||
.Item("Hide All Windows", ICON_MD_VISIBILITY_OFF,
|
||||
[this]() { HideAllWindows(); })
|
||||
.Item(
|
||||
"Maximize Current", ICON_MD_FULLSCREEN,
|
||||
[this]() { MaximizeCurrentWindow(); }, "F11")
|
||||
.Item("Restore All", ICON_MD_FULLSCREEN_EXIT,
|
||||
[this]() { RestoreAllWindows(); })
|
||||
.Item("Close All Floating", ICON_MD_CLOSE_FULLSCREEN,
|
||||
[this]() { CloseAllFloatingWindows(); })
|
||||
.EndMenu();
|
||||
|
||||
#ifdef YAZE_WITH_GRPC
|
||||
// Collaboration Menu - combined Agent + Network features
|
||||
menu_builder_.BeginMenu("Collaborate")
|
||||
.Item(
|
||||
"AI Agent Chat", ICON_MD_SMART_TOY,
|
||||
[this]() { agent_editor_.SetChatActive(true); }, "Ctrl+Shift+A",
|
||||
nullptr, [this]() { return agent_editor_.IsChatActive(); })
|
||||
.Item(
|
||||
"Proposal Drawer", ICON_MD_RATE_REVIEW,
|
||||
[this]() { show_proposal_drawer_ = !show_proposal_drawer_; }, nullptr,
|
||||
nullptr, [this]() { return show_proposal_drawer_; })
|
||||
.Separator()
|
||||
.Item("Host Session", ICON_MD_ADD_CIRCLE,
|
||||
[this]() {
|
||||
auto result = agent_editor_.HostSession("New Session");
|
||||
if (result.ok()) {
|
||||
toast_manager_.Show("Hosted session: " + result->session_name,
|
||||
ToastType::kSuccess);
|
||||
} else {
|
||||
toast_manager_.Show("Failed to host session: " +
|
||||
std::string(result.status().message()),
|
||||
ToastType::kError);
|
||||
}
|
||||
})
|
||||
.Item("Join Session", ICON_MD_LOGIN,
|
||||
[this]() { popup_manager_->Show("Join Collaboration Session"); })
|
||||
.Item(
|
||||
"Leave Session", ICON_MD_LOGOUT,
|
||||
[this]() {
|
||||
status_ = agent_editor_.LeaveSession();
|
||||
if (status_.ok()) {
|
||||
toast_manager_.Show("Left collaboration session",
|
||||
ToastType::kInfo);
|
||||
}
|
||||
},
|
||||
nullptr, [this]() { return agent_editor_.IsInSession(); })
|
||||
.Item(
|
||||
"Refresh Session", ICON_MD_REFRESH,
|
||||
[this]() {
|
||||
auto result = agent_editor_.RefreshSession();
|
||||
if (result.ok()) {
|
||||
toast_manager_.Show(
|
||||
"Session refreshed: " +
|
||||
std::to_string(result->participants.size()) +
|
||||
" participants",
|
||||
ToastType::kSuccess);
|
||||
}
|
||||
},
|
||||
nullptr, [this]() { return agent_editor_.IsInSession(); })
|
||||
.Separator()
|
||||
.Item("Connect to Server", ICON_MD_CLOUD_UPLOAD,
|
||||
[this]() { popup_manager_->Show("Connect to Server"); })
|
||||
.Item(
|
||||
"Disconnect from Server", ICON_MD_CLOUD_OFF,
|
||||
[this]() {
|
||||
agent_editor_.DisconnectFromServer();
|
||||
toast_manager_.Show("Disconnected from server", ToastType::kInfo);
|
||||
},
|
||||
nullptr, [this]() { return agent_editor_.IsConnectedToServer(); })
|
||||
.Separator()
|
||||
.Item("Capture Active Editor", ICON_MD_SCREENSHOT,
|
||||
[this]() {
|
||||
std::filesystem::path output;
|
||||
AgentEditor::CaptureConfig config;
|
||||
config.mode =
|
||||
AgentEditor::CaptureConfig::CaptureMode::kActiveEditor;
|
||||
status_ = agent_editor_.CaptureSnapshot(&output, config);
|
||||
})
|
||||
.Item("Capture Full Window", ICON_MD_FULLSCREEN,
|
||||
[this]() {
|
||||
std::filesystem::path output;
|
||||
AgentEditor::CaptureConfig config;
|
||||
config.mode =
|
||||
AgentEditor::CaptureConfig::CaptureMode::kFullWindow;
|
||||
status_ = agent_editor_.CaptureSnapshot(&output, config);
|
||||
})
|
||||
.Separator()
|
||||
.Item(
|
||||
"Local Mode", ICON_MD_FOLDER, [this]() { /* Set local mode */ },
|
||||
nullptr, nullptr,
|
||||
[this]() {
|
||||
return agent_editor_.GetCurrentMode() ==
|
||||
AgentEditor::CollaborationMode::kLocal;
|
||||
})
|
||||
.Item(
|
||||
"Network Mode", ICON_MD_WIFI, [this]() { /* Set network mode */ },
|
||||
nullptr, nullptr,
|
||||
[this]() {
|
||||
return agent_editor_.GetCurrentMode() ==
|
||||
AgentEditor::CollaborationMode::kNetwork;
|
||||
})
|
||||
.EndMenu();
|
||||
#endif
|
||||
|
||||
// Debug Menu - comprehensive development tools
|
||||
menu_builder_.BeginMenu("Debug");
|
||||
|
||||
#ifdef YAZE_ENABLE_TESTING
|
||||
// Testing and Validation section
|
||||
menu_builder_
|
||||
.Item(
|
||||
"Test Dashboard", ICON_MD_SCIENCE,
|
||||
[this]() { show_test_dashboard_ = true; }, "Ctrl+T")
|
||||
.Item("Run All Tests", ICON_MD_PLAY_ARROW,
|
||||
[this]() {
|
||||
[[maybe_unused]] auto status =
|
||||
test::TestManager::Get().RunAllTests();
|
||||
})
|
||||
.Item("Run Unit Tests", ICON_MD_INTEGRATION_INSTRUCTIONS,
|
||||
[this]() {
|
||||
[[maybe_unused]] auto status =
|
||||
test::TestManager::Get().RunTestsByCategory(
|
||||
test::TestCategory::kUnit);
|
||||
})
|
||||
.Item("Run Integration Tests", ICON_MD_MEMORY,
|
||||
[this]() {
|
||||
[[maybe_unused]] auto status =
|
||||
test::TestManager::Get().RunTestsByCategory(
|
||||
test::TestCategory::kIntegration);
|
||||
})
|
||||
.Item("Run UI Tests", ICON_MD_VISIBILITY,
|
||||
[this]() {
|
||||
[[maybe_unused]] auto status =
|
||||
test::TestManager::Get().RunTestsByCategory(
|
||||
test::TestCategory::kUI);
|
||||
})
|
||||
.Item("Run Performance Tests", ICON_MD_SPEED,
|
||||
[this]() {
|
||||
[[maybe_unused]] auto status =
|
||||
test::TestManager::Get().RunTestsByCategory(
|
||||
test::TestCategory::kPerformance);
|
||||
})
|
||||
.Item("Run Memory Tests", ICON_MD_STORAGE,
|
||||
[this]() {
|
||||
[[maybe_unused]] auto status =
|
||||
test::TestManager::Get().RunTestsByCategory(
|
||||
test::TestCategory::kMemory);
|
||||
})
|
||||
.Item("Clear Test Results", ICON_MD_CLEAR_ALL,
|
||||
[this]() { test::TestManager::Get().ClearResults(); })
|
||||
.Separator();
|
||||
#endif
|
||||
|
||||
// ROM and ASM Management
|
||||
menu_builder_.BeginSubMenu("ROM Analysis", ICON_MD_STORAGE)
|
||||
.Item(
|
||||
"ROM Information", ICON_MD_INFO,
|
||||
[this]() { popup_manager_->Show("ROM Information"); }, nullptr,
|
||||
[this]() { return current_rom_ && current_rom_->is_loaded(); })
|
||||
#ifdef YAZE_ENABLE_TESTING
|
||||
.Item(
|
||||
"Data Integrity Check", ICON_MD_ANALYTICS,
|
||||
[this]() {
|
||||
if (current_rom_) {
|
||||
[[maybe_unused]] auto status =
|
||||
test::TestManager::Get().RunTestSuite("RomIntegrity");
|
||||
toast_manager_.Show("Running ROM integrity tests...",
|
||||
ToastType::kInfo);
|
||||
}
|
||||
},
|
||||
nullptr,
|
||||
[this]() { return current_rom_ && current_rom_->is_loaded(); })
|
||||
.Item(
|
||||
"Test Save/Load", ICON_MD_SAVE_ALT,
|
||||
[this]() {
|
||||
if (current_rom_) {
|
||||
[[maybe_unused]] auto status =
|
||||
test::TestManager::Get().RunTestSuite("RomSaveLoad");
|
||||
toast_manager_.Show("Running ROM save/load tests...",
|
||||
ToastType::kInfo);
|
||||
}
|
||||
},
|
||||
nullptr,
|
||||
[this]() { return current_rom_ && current_rom_->is_loaded(); })
|
||||
#endif
|
||||
.EndMenu()
|
||||
.BeginSubMenu("ZSCustomOverworld", ICON_MD_CODE)
|
||||
.Item(
|
||||
"Check ROM Version", ICON_MD_INFO,
|
||||
[this]() {
|
||||
if (current_rom_) {
|
||||
uint8_t version =
|
||||
(*current_rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
std::string version_str = (version == 0xFF)
|
||||
? "Vanilla"
|
||||
: absl::StrFormat("v%d", version);
|
||||
toast_manager_.Show(
|
||||
absl::StrFormat("ROM: %s | ZSCustomOverworld: %s",
|
||||
current_rom_->title().c_str(),
|
||||
version_str.c_str()),
|
||||
ToastType::kInfo, 5.0f);
|
||||
}
|
||||
},
|
||||
nullptr,
|
||||
[this]() { return current_rom_ && current_rom_->is_loaded(); })
|
||||
.Item(
|
||||
"Upgrade ROM", ICON_MD_UPGRADE,
|
||||
[this]() {
|
||||
if (current_rom_) {
|
||||
toast_manager_.Show("Use Overworld Editor to upgrade ROM version",
|
||||
ToastType::kInfo, 4.0f);
|
||||
}
|
||||
},
|
||||
nullptr,
|
||||
[this]() { return current_rom_ && current_rom_->is_loaded(); })
|
||||
.Item("Toggle Custom Loading", ICON_MD_SETTINGS,
|
||||
[this]() {
|
||||
auto& flags = core::FeatureFlags::get();
|
||||
flags.overworld.kLoadCustomOverworld =
|
||||
!flags.overworld.kLoadCustomOverworld;
|
||||
toast_manager_.Show(
|
||||
absl::StrFormat("Custom Overworld Loading: %s",
|
||||
flags.overworld.kLoadCustomOverworld
|
||||
? "Enabled"
|
||||
: "Disabled"),
|
||||
ToastType::kInfo);
|
||||
})
|
||||
.EndMenu()
|
||||
.BeginSubMenu("Asar Integration", ICON_MD_BUILD)
|
||||
.Item("Asar Status", ICON_MD_INFO,
|
||||
[this]() { popup_manager_->Show("Asar Integration"); })
|
||||
.Item(
|
||||
"Toggle ASM Patch", ICON_MD_CODE,
|
||||
[this]() {
|
||||
if (current_rom_) {
|
||||
auto& flags = core::FeatureFlags::get();
|
||||
flags.overworld.kApplyZSCustomOverworldASM =
|
||||
!flags.overworld.kApplyZSCustomOverworldASM;
|
||||
toast_manager_.Show(
|
||||
absl::StrFormat("ZSCustomOverworld ASM Application: %s",
|
||||
flags.overworld.kApplyZSCustomOverworldASM
|
||||
? "Enabled"
|
||||
: "Disabled"),
|
||||
ToastType::kInfo);
|
||||
}
|
||||
},
|
||||
nullptr,
|
||||
[this]() { return current_rom_ && current_rom_->is_loaded(); })
|
||||
.Item("Load ASM File", ICON_MD_FOLDER_OPEN,
|
||||
[this]() {
|
||||
toast_manager_.Show("ASM file loading not yet implemented",
|
||||
ToastType::kWarning);
|
||||
})
|
||||
.EndMenu()
|
||||
.Separator()
|
||||
// Development Tools
|
||||
.Item("Memory Editor", ICON_MD_MEMORY,
|
||||
[this]() {
|
||||
gui::EditorCardManager::Get().ShowCard("memory.hex_editor");
|
||||
})
|
||||
.Item("Assembly Editor", ICON_MD_CODE,
|
||||
[this]() {
|
||||
gui::EditorCardManager::Get().ShowCard("assembly.editor");
|
||||
})
|
||||
.Item("Feature Flags", ICON_MD_FLAG,
|
||||
[this]() { popup_manager_->Show("Feature Flags"); })
|
||||
.Separator()
|
||||
.Item("Performance Dashboard", ICON_MD_SPEED,
|
||||
[this]() { show_performance_dashboard_ = true; })
|
||||
#ifdef YAZE_WITH_GRPC
|
||||
.Item("Agent Proposals", ICON_MD_PREVIEW,
|
||||
[this]() { proposal_drawer_.Toggle(); })
|
||||
#endif
|
||||
.Separator()
|
||||
.Item(
|
||||
"ImGui Demo", ICON_MD_HELP, [this]() { show_imgui_demo_ = true; },
|
||||
nullptr, nullptr, [this]() { return show_imgui_demo_; })
|
||||
.Item(
|
||||
"ImGui Metrics", ICON_MD_ANALYTICS,
|
||||
[this]() { show_imgui_metrics_ = true; }, nullptr, nullptr,
|
||||
[this]() { return show_imgui_metrics_; })
|
||||
.EndMenu();
|
||||
|
||||
// Help Menu
|
||||
menu_builder_.BeginMenu("Help")
|
||||
.Item("Getting Started", ICON_MD_PLAY_ARROW,
|
||||
[this]() { popup_manager_->Show("Getting Started"); })
|
||||
.Item(
|
||||
"About", ICON_MD_INFO, [this]() { popup_manager_->Show("About"); },
|
||||
"F1")
|
||||
.EndMenu();
|
||||
|
||||
menu_builder_.Draw();
|
||||
// Delegate to MenuOrchestrator for clean separation of concerns
|
||||
if (menu_orchestrator_) {
|
||||
menu_orchestrator_->BuildMainMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorManager::DrawMenuBarExtras() {
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "app/editor/system/toast_manager.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/editor/system/editor_registry.h"
|
||||
#include "app/editor/system/menu_orchestrator.h"
|
||||
#include "app/editor/system/project_manager.h"
|
||||
#include "app/editor/system/rom_file_manager.h"
|
||||
#include "app/editor/system/session_card_registry.h"
|
||||
@@ -354,6 +355,7 @@ class EditorManager {
|
||||
|
||||
// New delegated components
|
||||
EditorRegistry editor_registry_;
|
||||
std::unique_ptr<MenuOrchestrator> menu_orchestrator_;
|
||||
ProjectManager project_manager_;
|
||||
RomFileManager rom_file_manager_;
|
||||
SessionCardRegistry card_registry_;
|
||||
|
||||
523
src/app/editor/system/menu_orchestrator.cc
Normal file
523
src/app/editor/system/menu_orchestrator.cc
Normal file
@@ -0,0 +1,523 @@
|
||||
#include "menu_orchestrator.h"
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/editor/editor.h"
|
||||
#include "app/editor/system/editor_registry.h"
|
||||
#include "app/editor/system/project_manager.h"
|
||||
#include "app/editor/system/rom_file_manager.h"
|
||||
#include "app/editor/system/toast_manager.h"
|
||||
#include "app/editor/ui/menu_builder.h"
|
||||
#include "app/editor/ui/session_coordinator.h"
|
||||
#include "app/gui/core/icons.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
|
||||
MenuOrchestrator::MenuOrchestrator(
|
||||
MenuBuilder& menu_builder,
|
||||
RomFileManager& rom_manager,
|
||||
ProjectManager& project_manager,
|
||||
EditorRegistry& editor_registry,
|
||||
SessionCoordinator& session_coordinator,
|
||||
ToastManager& toast_manager)
|
||||
: menu_builder_(menu_builder),
|
||||
rom_manager_(rom_manager),
|
||||
project_manager_(project_manager),
|
||||
editor_registry_(editor_registry),
|
||||
session_coordinator_(session_coordinator),
|
||||
toast_manager_(toast_manager) {
|
||||
}
|
||||
|
||||
void MenuOrchestrator::BuildMainMenu() {
|
||||
ClearMenu();
|
||||
|
||||
// Build all menu sections in order
|
||||
BuildFileMenu();
|
||||
BuildEditMenu();
|
||||
BuildViewMenu();
|
||||
BuildToolsMenu();
|
||||
BuildWindowMenu();
|
||||
BuildHelpMenu();
|
||||
|
||||
menu_needs_refresh_ = false;
|
||||
}
|
||||
|
||||
void MenuOrchestrator::BuildFileMenu() {
|
||||
menu_builder_.BeginMenu("File");
|
||||
AddFileMenuItems();
|
||||
menu_builder_.EndMenu();
|
||||
}
|
||||
|
||||
void MenuOrchestrator::AddFileMenuItems() {
|
||||
// ROM Operations
|
||||
menu_builder_
|
||||
.Item("Open ROM", ICON_MD_FILE_OPEN,
|
||||
[this]() { OnOpenRom(); }, "Ctrl+O")
|
||||
.Item("Save ROM", ICON_MD_SAVE,
|
||||
[this]() { OnSaveRom(); }, "Ctrl+S",
|
||||
[this]() { return CanSaveRom(); })
|
||||
.Item("Save As...", ICON_MD_SAVE_AS,
|
||||
[this]() { OnSaveRomAs(); }, nullptr,
|
||||
[this]() { return CanSaveRom(); })
|
||||
.Separator();
|
||||
|
||||
// Project Operations
|
||||
menu_builder_
|
||||
.Item("New Project", ICON_MD_CREATE_NEW_FOLDER,
|
||||
[this]() { OnCreateProject(); })
|
||||
.Item("Open Project", ICON_MD_FOLDER_OPEN,
|
||||
[this]() { OnOpenProject(); })
|
||||
.Item("Save Project", ICON_MD_SAVE,
|
||||
[this]() { OnSaveProject(); }, nullptr,
|
||||
[this]() { return CanSaveProject(); })
|
||||
.Item("Save Project As...", ICON_MD_SAVE_AS,
|
||||
[this]() { OnSaveProjectAs(); }, nullptr,
|
||||
[this]() { return CanSaveProject(); })
|
||||
.Separator();
|
||||
|
||||
// ROM Information and Validation
|
||||
menu_builder_
|
||||
.Item("ROM Information", ICON_MD_INFO,
|
||||
[this]() {
|
||||
// TODO: Show ROM info popup
|
||||
toast_manager_.Show("ROM Information", ToastType::kInfo);
|
||||
}, nullptr,
|
||||
[this]() { return HasActiveRom(); })
|
||||
.Item("Create Backup", ICON_MD_BACKUP,
|
||||
[this]() {
|
||||
if (HasActiveRom()) {
|
||||
auto status = rom_manager_.CreateBackup();
|
||||
if (!status.ok()) {
|
||||
toast_manager_.Show(
|
||||
absl::StrFormat("Backup failed: %s", status.message()),
|
||||
ToastType::kError);
|
||||
}
|
||||
}
|
||||
}, nullptr,
|
||||
[this]() { return HasActiveRom(); })
|
||||
.Item("Validate ROM", ICON_MD_CHECK_CIRCLE,
|
||||
[this]() {
|
||||
if (HasActiveRom()) {
|
||||
auto status = rom_manager_.ValidateRom();
|
||||
if (!status.ok()) {
|
||||
toast_manager_.Show(
|
||||
absl::StrFormat("Validation failed: %s", status.message()),
|
||||
ToastType::kError);
|
||||
}
|
||||
}
|
||||
}, nullptr,
|
||||
[this]() { return HasActiveRom(); })
|
||||
.Separator();
|
||||
|
||||
// Settings and Quit
|
||||
menu_builder_
|
||||
.Item("Settings", ICON_MD_SETTINGS,
|
||||
[this]() {
|
||||
// TODO: Show settings editor
|
||||
toast_manager_.Show("Settings", ToastType::kInfo);
|
||||
})
|
||||
.Separator()
|
||||
.Item("Quit", ICON_MD_EXIT_TO_APP,
|
||||
[this]() {
|
||||
// TODO: Signal quit to EditorManager
|
||||
toast_manager_.Show("Quit requested", ToastType::kInfo);
|
||||
}, "Ctrl+Q");
|
||||
}
|
||||
|
||||
void MenuOrchestrator::BuildEditMenu() {
|
||||
menu_builder_.BeginMenu("Edit");
|
||||
AddEditMenuItems();
|
||||
menu_builder_.EndMenu();
|
||||
}
|
||||
|
||||
void MenuOrchestrator::AddEditMenuItems() {
|
||||
// Undo/Redo operations
|
||||
menu_builder_
|
||||
.Item("Undo", ICON_MD_UNDO,
|
||||
[this]() {
|
||||
// TODO: Delegate to current editor
|
||||
toast_manager_.Show("Undo", ToastType::kInfo);
|
||||
}, "Ctrl+Z",
|
||||
[this]() { return HasCurrentEditor(); })
|
||||
.Item("Redo", ICON_MD_REDO,
|
||||
[this]() {
|
||||
// TODO: Delegate to current editor
|
||||
toast_manager_.Show("Redo", ToastType::kInfo);
|
||||
}, "Ctrl+Y",
|
||||
[this]() { return HasCurrentEditor(); })
|
||||
.Separator();
|
||||
|
||||
// Clipboard operations
|
||||
menu_builder_
|
||||
.Item("Cut", ICON_MD_CONTENT_CUT,
|
||||
[this]() {
|
||||
// TODO: Delegate to current editor
|
||||
toast_manager_.Show("Cut", ToastType::kInfo);
|
||||
}, "Ctrl+X",
|
||||
[this]() { return HasCurrentEditor(); })
|
||||
.Item("Copy", ICON_MD_CONTENT_COPY,
|
||||
[this]() {
|
||||
// TODO: Delegate to current editor
|
||||
toast_manager_.Show("Copy", ToastType::kInfo);
|
||||
}, "Ctrl+C",
|
||||
[this]() { return HasCurrentEditor(); })
|
||||
.Item("Paste", ICON_MD_CONTENT_PASTE,
|
||||
[this]() {
|
||||
// TODO: Delegate to current editor
|
||||
toast_manager_.Show("Paste", ToastType::kInfo);
|
||||
}, "Ctrl+V",
|
||||
[this]() { return HasCurrentEditor(); })
|
||||
.Separator();
|
||||
|
||||
// Search operations
|
||||
menu_builder_
|
||||
.Item("Find", ICON_MD_SEARCH,
|
||||
[this]() {
|
||||
// TODO: Delegate to current editor
|
||||
toast_manager_.Show("Find", ToastType::kInfo);
|
||||
}, "Ctrl+F",
|
||||
[this]() { return HasCurrentEditor(); })
|
||||
.Item("Find in Files", ICON_MD_SEARCH,
|
||||
[this]() { OnShowGlobalSearch(); }, "Ctrl+Shift+F");
|
||||
}
|
||||
|
||||
void MenuOrchestrator::BuildViewMenu() {
|
||||
menu_builder_.BeginMenu("View");
|
||||
AddViewMenuItems();
|
||||
menu_builder_.EndMenu();
|
||||
}
|
||||
|
||||
void MenuOrchestrator::AddViewMenuItems() {
|
||||
// Editor Selection
|
||||
menu_builder_
|
||||
.Item("Editor Selection", ICON_MD_DASHBOARD,
|
||||
[this]() { OnShowEditorSelection(); }, "Ctrl+E")
|
||||
.Separator();
|
||||
|
||||
// Individual Editor Shortcuts
|
||||
menu_builder_
|
||||
.Item("Overworld", ICON_MD_MAP,
|
||||
[this]() { OnSwitchToEditor(EditorType::kOverworld); }, "Ctrl+1")
|
||||
.Item("Dungeon", ICON_MD_CASTLE,
|
||||
[this]() { OnSwitchToEditor(EditorType::kDungeon); }, "Ctrl+2")
|
||||
.Item("Graphics", ICON_MD_IMAGE,
|
||||
[this]() { OnSwitchToEditor(EditorType::kGraphics); }, "Ctrl+3")
|
||||
.Item("Sprites", ICON_MD_TOYS,
|
||||
[this]() { OnSwitchToEditor(EditorType::kSprite); }, "Ctrl+4")
|
||||
.Item("Messages", ICON_MD_CHAT_BUBBLE,
|
||||
[this]() { OnSwitchToEditor(EditorType::kMessage); }, "Ctrl+5")
|
||||
.Item("Music", ICON_MD_MUSIC_NOTE,
|
||||
[this]() { OnSwitchToEditor(EditorType::kMusic); }, "Ctrl+6")
|
||||
.Item("Palettes", ICON_MD_PALETTE,
|
||||
[this]() { OnSwitchToEditor(EditorType::kPalette); }, "Ctrl+7")
|
||||
.Item("Screens", ICON_MD_TV,
|
||||
[this]() { OnSwitchToEditor(EditorType::kScreen); }, "Ctrl+8")
|
||||
.Item("Hex Editor", ICON_MD_DATA_ARRAY,
|
||||
[this]() { OnSwitchToEditor(EditorType::kHex); }, "Ctrl+9")
|
||||
.Item("Assembly", ICON_MD_CODE,
|
||||
[this]() { OnSwitchToEditor(EditorType::kAssembly); }, "Ctrl+0")
|
||||
.Separator();
|
||||
|
||||
// Display Settings
|
||||
menu_builder_
|
||||
.Item("Display Settings", ICON_MD_DISPLAY_SETTINGS,
|
||||
[this]() { OnShowDisplaySettings(); });
|
||||
}
|
||||
|
||||
void MenuOrchestrator::BuildToolsMenu() {
|
||||
menu_builder_.BeginMenu("Tools");
|
||||
AddToolsMenuItems();
|
||||
menu_builder_.EndMenu();
|
||||
}
|
||||
|
||||
void MenuOrchestrator::AddToolsMenuItems() {
|
||||
// Development Tools
|
||||
menu_builder_
|
||||
.Item("Global Search", ICON_MD_SEARCH,
|
||||
[this]() { OnShowGlobalSearch(); }, "Ctrl+Shift+F")
|
||||
.Item("Performance Dashboard", ICON_MD_SPEED,
|
||||
[this]() { OnShowPerformanceDashboard(); })
|
||||
.Separator();
|
||||
|
||||
// Debug Tools
|
||||
menu_builder_
|
||||
.Item("ImGui Demo", ICON_MD_BUG_REPORT,
|
||||
[this]() { OnShowImGuiDemo(); })
|
||||
.Item("ImGui Metrics", ICON_MD_ANALYTICS,
|
||||
[this]() { OnShowImGuiMetrics(); });
|
||||
}
|
||||
|
||||
void MenuOrchestrator::BuildWindowMenu() {
|
||||
menu_builder_.BeginMenu("Window");
|
||||
AddWindowMenuItems();
|
||||
menu_builder_.EndMenu();
|
||||
}
|
||||
|
||||
void MenuOrchestrator::AddWindowMenuItems() {
|
||||
// Window Management
|
||||
menu_builder_
|
||||
.Item("Show All Windows", ICON_MD_VISIBILITY,
|
||||
[this]() { OnShowAllWindows(); })
|
||||
.Item("Hide All Windows", ICON_MD_VISIBILITY_OFF,
|
||||
[this]() { OnHideAllWindows(); })
|
||||
.Separator();
|
||||
|
||||
// Layout Management
|
||||
menu_builder_
|
||||
.Item("Reset Layout", ICON_MD_RESTORE,
|
||||
[this]() { OnResetWorkspaceLayout(); })
|
||||
.Item("Save Layout", ICON_MD_SAVE,
|
||||
[this]() { OnSaveWorkspaceLayout(); })
|
||||
.Item("Load Layout", ICON_MD_FOLDER_OPEN,
|
||||
[this]() { OnLoadWorkspaceLayout(); });
|
||||
|
||||
// Session Management (if multiple sessions)
|
||||
if (HasMultipleSessions()) {
|
||||
menu_builder_
|
||||
.Separator()
|
||||
.Item("New Session", ICON_MD_ADD,
|
||||
[this]() { OnCreateNewSession(); })
|
||||
.Item("Duplicate Session", ICON_MD_CONTENT_COPY,
|
||||
[this]() { OnDuplicateCurrentSession(); })
|
||||
.Item("Close Session", ICON_MD_CLOSE,
|
||||
[this]() { OnCloseCurrentSession(); });
|
||||
}
|
||||
}
|
||||
|
||||
void MenuOrchestrator::BuildHelpMenu() {
|
||||
menu_builder_.BeginMenu("Help");
|
||||
AddHelpMenuItems();
|
||||
menu_builder_.EndMenu();
|
||||
}
|
||||
|
||||
void MenuOrchestrator::AddHelpMenuItems() {
|
||||
menu_builder_
|
||||
.Item("User Guide", ICON_MD_HELP,
|
||||
[this]() { OnShowUserGuide(); })
|
||||
.Item("Keyboard Shortcuts", ICON_MD_KEYBOARD,
|
||||
[this]() { OnShowKeyboardShortcuts(); })
|
||||
.Separator()
|
||||
.Item("About", ICON_MD_INFO,
|
||||
[this]() { OnShowAbout(); });
|
||||
}
|
||||
|
||||
// Menu state management
|
||||
void MenuOrchestrator::ClearMenu() {
|
||||
menu_builder_.Clear();
|
||||
}
|
||||
|
||||
void MenuOrchestrator::RefreshMenu() {
|
||||
menu_needs_refresh_ = true;
|
||||
}
|
||||
|
||||
// Menu item callbacks - delegate to appropriate managers
|
||||
void MenuOrchestrator::OnOpenRom() {
|
||||
auto status = rom_manager_.LoadRom();
|
||||
if (!status.ok()) {
|
||||
toast_manager_.Show(
|
||||
absl::StrFormat("Failed to load ROM: %s", status.message()),
|
||||
ToastType::kError);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnSaveRom() {
|
||||
auto status = rom_manager_.SaveRom();
|
||||
if (!status.ok()) {
|
||||
toast_manager_.Show(
|
||||
absl::StrFormat("Failed to save ROM: %s", status.message()),
|
||||
ToastType::kError);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnSaveRomAs() {
|
||||
// TODO: Show save dialog and delegate to rom_manager_
|
||||
toast_manager_.Show("Save ROM As", ToastType::kInfo);
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnCreateProject() {
|
||||
auto status = project_manager_.CreateNewProject();
|
||||
if (!status.ok()) {
|
||||
toast_manager_.Show(
|
||||
absl::StrFormat("Failed to create project: %s", status.message()),
|
||||
ToastType::kError);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnOpenProject() {
|
||||
auto status = project_manager_.OpenProject();
|
||||
if (!status.ok()) {
|
||||
toast_manager_.Show(
|
||||
absl::StrFormat("Failed to open project: %s", status.message()),
|
||||
ToastType::kError);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnSaveProject() {
|
||||
auto status = project_manager_.SaveProject();
|
||||
if (!status.ok()) {
|
||||
toast_manager_.Show(
|
||||
absl::StrFormat("Failed to save project: %s", status.message()),
|
||||
ToastType::kError);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnSaveProjectAs() {
|
||||
auto status = project_manager_.SaveProjectAs();
|
||||
if (!status.ok()) {
|
||||
toast_manager_.Show(
|
||||
absl::StrFormat("Failed to save project as: %s", status.message()),
|
||||
ToastType::kError);
|
||||
}
|
||||
}
|
||||
|
||||
// Editor-specific menu actions
|
||||
void MenuOrchestrator::OnSwitchToEditor(EditorType editor_type) {
|
||||
editor_registry_.SwitchToEditor(editor_type);
|
||||
toast_manager_.Show(
|
||||
absl::StrFormat("Switched to %s",
|
||||
editor_registry_.GetEditorDisplayName(editor_type)),
|
||||
ToastType::kInfo);
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnShowEditorSelection() {
|
||||
// TODO: Show editor selection dialog
|
||||
toast_manager_.Show("Editor Selection", ToastType::kInfo);
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnShowDisplaySettings() {
|
||||
// TODO: Show display settings dialog
|
||||
toast_manager_.Show("Display Settings", ToastType::kInfo);
|
||||
}
|
||||
|
||||
// Session management menu actions
|
||||
void MenuOrchestrator::OnCreateNewSession() {
|
||||
session_coordinator_.CreateNewSession();
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnDuplicateCurrentSession() {
|
||||
session_coordinator_.DuplicateCurrentSession();
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnCloseCurrentSession() {
|
||||
session_coordinator_.CloseCurrentSession();
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnSwitchToSession(size_t session_index) {
|
||||
session_coordinator_.SwitchToSession(session_index);
|
||||
}
|
||||
|
||||
// Window management menu actions
|
||||
void MenuOrchestrator::OnShowAllWindows() {
|
||||
// TODO: Delegate to WindowDelegate
|
||||
toast_manager_.Show("Show All Windows", ToastType::kInfo);
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnHideAllWindows() {
|
||||
// TODO: Delegate to WindowDelegate
|
||||
toast_manager_.Show("Hide All Windows", ToastType::kInfo);
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnResetWorkspaceLayout() {
|
||||
// TODO: Delegate to WindowDelegate
|
||||
toast_manager_.Show("Reset Workspace Layout", ToastType::kInfo);
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnSaveWorkspaceLayout() {
|
||||
// TODO: Delegate to WindowDelegate
|
||||
toast_manager_.Show("Save Workspace Layout", ToastType::kInfo);
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnLoadWorkspaceLayout() {
|
||||
// TODO: Delegate to WindowDelegate
|
||||
toast_manager_.Show("Load Workspace Layout", ToastType::kInfo);
|
||||
}
|
||||
|
||||
// Tool menu actions
|
||||
void MenuOrchestrator::OnShowGlobalSearch() {
|
||||
// TODO: Show global search dialog
|
||||
toast_manager_.Show("Global Search", ToastType::kInfo);
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnShowPerformanceDashboard() {
|
||||
// TODO: Show performance dashboard
|
||||
toast_manager_.Show("Performance Dashboard", ToastType::kInfo);
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnShowImGuiDemo() {
|
||||
// TODO: Show ImGui demo
|
||||
toast_manager_.Show("ImGui Demo", ToastType::kInfo);
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnShowImGuiMetrics() {
|
||||
// TODO: Show ImGui metrics
|
||||
toast_manager_.Show("ImGui Metrics", ToastType::kInfo);
|
||||
}
|
||||
|
||||
// Help menu actions
|
||||
void MenuOrchestrator::OnShowAbout() {
|
||||
// TODO: Show about dialog
|
||||
toast_manager_.Show("About YAZE", ToastType::kInfo);
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnShowKeyboardShortcuts() {
|
||||
// TODO: Show keyboard shortcuts dialog
|
||||
toast_manager_.Show("Keyboard Shortcuts", ToastType::kInfo);
|
||||
}
|
||||
|
||||
void MenuOrchestrator::OnShowUserGuide() {
|
||||
// TODO: Show user guide
|
||||
toast_manager_.Show("User Guide", ToastType::kInfo);
|
||||
}
|
||||
|
||||
// Menu item validation helpers
|
||||
bool MenuOrchestrator::CanSaveRom() const {
|
||||
return rom_manager_.IsRomLoaded();
|
||||
}
|
||||
|
||||
bool MenuOrchestrator::CanSaveProject() const {
|
||||
return project_manager_.HasActiveProject();
|
||||
}
|
||||
|
||||
bool MenuOrchestrator::HasActiveRom() const {
|
||||
return rom_manager_.IsRomLoaded();
|
||||
}
|
||||
|
||||
bool MenuOrchestrator::HasActiveProject() const {
|
||||
return project_manager_.HasActiveProject();
|
||||
}
|
||||
|
||||
bool MenuOrchestrator::HasCurrentEditor() const {
|
||||
// TODO: Check if there's a current active editor
|
||||
return true; // Placeholder
|
||||
}
|
||||
|
||||
bool MenuOrchestrator::HasMultipleSessions() const {
|
||||
return session_coordinator_.HasMultipleSessions();
|
||||
}
|
||||
|
||||
// Menu item text generation
|
||||
std::string MenuOrchestrator::GetRomFilename() const {
|
||||
return rom_manager_.GetRomFilename();
|
||||
}
|
||||
|
||||
std::string MenuOrchestrator::GetProjectName() const {
|
||||
return project_manager_.GetProjectName();
|
||||
}
|
||||
|
||||
std::string MenuOrchestrator::GetCurrentEditorName() const {
|
||||
// TODO: Get current editor name
|
||||
return "Unknown Editor";
|
||||
}
|
||||
|
||||
// Shortcut key management
|
||||
std::string MenuOrchestrator::GetShortcutForAction(const std::string& action) const {
|
||||
// TODO: Implement shortcut mapping
|
||||
return "";
|
||||
}
|
||||
|
||||
void MenuOrchestrator::RegisterGlobalShortcuts() {
|
||||
// TODO: Register global keyboard shortcuts
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace yaze
|
||||
144
src/app/editor/system/menu_orchestrator.h
Normal file
144
src/app/editor/system/menu_orchestrator.h
Normal file
@@ -0,0 +1,144 @@
|
||||
#ifndef YAZE_APP_EDITOR_SYSTEM_MENU_ORCHESTRATOR_H_
|
||||
#define YAZE_APP_EDITOR_SYSTEM_MENU_ORCHESTRATOR_H_
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "app/editor/editor.h"
|
||||
#include "app/editor/ui/menu_builder.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
|
||||
// Forward declarations to avoid circular dependencies
|
||||
class EditorManager;
|
||||
class RomFileManager;
|
||||
class ProjectManager;
|
||||
class EditorRegistry;
|
||||
class SessionCoordinator;
|
||||
class ToastManager;
|
||||
|
||||
/**
|
||||
* @class MenuOrchestrator
|
||||
* @brief Handles all menu building and UI coordination logic
|
||||
*
|
||||
* Extracted from EditorManager to provide focused menu management:
|
||||
* - Menu structure and organization
|
||||
* - Menu item callbacks and shortcuts
|
||||
* - Editor-specific menu items
|
||||
* - Session-aware menu updates
|
||||
* - Menu state management
|
||||
*
|
||||
* This class follows the Single Responsibility Principle by focusing solely
|
||||
* on menu construction and coordination, delegating actual operations to
|
||||
* specialized managers.
|
||||
*/
|
||||
class MenuOrchestrator {
|
||||
public:
|
||||
// Constructor takes references to the managers it coordinates with
|
||||
MenuOrchestrator(MenuBuilder& menu_builder,
|
||||
RomFileManager& rom_manager,
|
||||
ProjectManager& project_manager,
|
||||
EditorRegistry& editor_registry,
|
||||
SessionCoordinator& session_coordinator,
|
||||
ToastManager& toast_manager);
|
||||
~MenuOrchestrator() = default;
|
||||
|
||||
// Non-copyable due to reference members
|
||||
MenuOrchestrator(const MenuOrchestrator&) = delete;
|
||||
MenuOrchestrator& operator=(const MenuOrchestrator&) = delete;
|
||||
|
||||
// Main menu building interface
|
||||
void BuildMainMenu();
|
||||
void BuildFileMenu();
|
||||
void BuildEditMenu();
|
||||
void BuildViewMenu();
|
||||
void BuildToolsMenu();
|
||||
void BuildWindowMenu();
|
||||
void BuildHelpMenu();
|
||||
|
||||
// Menu state management
|
||||
void ClearMenu();
|
||||
void RefreshMenu();
|
||||
|
||||
// Menu item callbacks (delegated to appropriate managers)
|
||||
void OnOpenRom();
|
||||
void OnSaveRom();
|
||||
void OnSaveRomAs();
|
||||
void OnCreateProject();
|
||||
void OnOpenProject();
|
||||
void OnSaveProject();
|
||||
void OnSaveProjectAs();
|
||||
|
||||
// Editor-specific menu actions
|
||||
void OnSwitchToEditor(EditorType editor_type);
|
||||
void OnShowEditorSelection();
|
||||
void OnShowDisplaySettings();
|
||||
|
||||
// Session management menu actions
|
||||
void OnCreateNewSession();
|
||||
void OnDuplicateCurrentSession();
|
||||
void OnCloseCurrentSession();
|
||||
void OnSwitchToSession(size_t session_index);
|
||||
|
||||
// Window management menu actions
|
||||
void OnShowAllWindows();
|
||||
void OnHideAllWindows();
|
||||
void OnResetWorkspaceLayout();
|
||||
void OnSaveWorkspaceLayout();
|
||||
void OnLoadWorkspaceLayout();
|
||||
|
||||
// Tool menu actions
|
||||
void OnShowGlobalSearch();
|
||||
void OnShowPerformanceDashboard();
|
||||
void OnShowImGuiDemo();
|
||||
void OnShowImGuiMetrics();
|
||||
|
||||
// Help menu actions
|
||||
void OnShowAbout();
|
||||
void OnShowKeyboardShortcuts();
|
||||
void OnShowUserGuide();
|
||||
|
||||
private:
|
||||
// References to coordinated managers
|
||||
MenuBuilder& menu_builder_;
|
||||
RomFileManager& rom_manager_;
|
||||
ProjectManager& project_manager_;
|
||||
EditorRegistry& editor_registry_;
|
||||
SessionCoordinator& session_coordinator_;
|
||||
ToastManager& toast_manager_;
|
||||
|
||||
// Menu state
|
||||
bool menu_needs_refresh_ = false;
|
||||
|
||||
// Helper methods for menu construction
|
||||
void AddFileMenuItems();
|
||||
void AddEditMenuItems();
|
||||
void AddViewMenuItems();
|
||||
void AddToolsMenuItems();
|
||||
void AddWindowMenuItems();
|
||||
void AddHelpMenuItems();
|
||||
|
||||
// Menu item validation helpers
|
||||
bool CanSaveRom() const;
|
||||
bool CanSaveProject() const;
|
||||
bool HasActiveRom() const;
|
||||
bool HasActiveProject() const;
|
||||
bool HasCurrentEditor() const;
|
||||
bool HasMultipleSessions() const;
|
||||
|
||||
// Menu item text generation
|
||||
std::string GetRomFilename() const;
|
||||
std::string GetProjectName() const;
|
||||
std::string GetCurrentEditorName() const;
|
||||
|
||||
// Shortcut key management
|
||||
std::string GetShortcutForAction(const std::string& action) const;
|
||||
void RegisterGlobalShortcuts();
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_SYSTEM_MENU_ORCHESTRATOR_H_
|
||||
Reference in New Issue
Block a user