refactor(editor): enhance popup management and initialization order
- Updated EditorManager to initialize PopupManager in the constructor, ensuring safe access to popups during menu operations. - Refactored MenuOrchestrator to utilize PopupID constants for popup management, improving clarity and maintainability. - Enhanced PopupManager to register popups with structured definitions, allowing for better organization and future expansion. Benefits: - Streamlines the initialization process, preventing potential crashes due to uninitialized components. - Improves the organization of popup management, leading to a more intuitive user experience and easier maintenance.
This commit is contained in:
@@ -144,28 +144,46 @@ EditorManager::EditorManager()
|
|||||||
// - EditorCardRegistry: Card-based editor UI management
|
// - EditorCardRegistry: Card-based editor UI management
|
||||||
// - ShortcutConfigurator: Keyboard shortcut registration
|
// - ShortcutConfigurator: Keyboard shortcut registration
|
||||||
// - WindowDelegate: Window layout operations
|
// - WindowDelegate: Window layout operations
|
||||||
|
// - PopupManager: Modal popup/dialog management
|
||||||
//
|
//
|
||||||
// EditorManager retains:
|
// EditorManager retains:
|
||||||
// - Session storage (sessions_) and current pointers (current_rom_, etc.)
|
// - Session storage (sessions_) and current pointers (current_rom_, etc.)
|
||||||
// - Main update loop (iterates sessions, calls editor updates)
|
// - Main update loop (iterates sessions, calls editor updates)
|
||||||
// - Asset loading (Initialize/Load on all editors)
|
// - Asset loading (Initialize/Load on all editors)
|
||||||
// - Session ID tracking (current_session_id_)
|
// - Session ID tracking (current_session_id_)
|
||||||
|
//
|
||||||
|
// INITIALIZATION ORDER (CRITICAL):
|
||||||
|
// 1. PopupManager - MUST be first, MenuOrchestrator/UICoordinator take ref to it
|
||||||
|
// 2. SessionCoordinator - Independent, can be early
|
||||||
|
// 3. MenuOrchestrator - Depends on PopupManager, SessionCoordinator
|
||||||
|
// 4. UICoordinator - Depends on PopupManager, SessionCoordinator
|
||||||
|
// 5. ShortcutConfigurator - Created in Initialize(), depends on all above
|
||||||
|
//
|
||||||
|
// If this order is violated, you will get SIGSEGV crashes when menu callbacks
|
||||||
|
// try to call popup_manager_.Show() with an uninitialized PopupManager!
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
// SessionCoordinator: Manages session lifecycle and session-specific UI
|
// STEP 1: Initialize PopupManager FIRST
|
||||||
|
popup_manager_ = std::make_unique<PopupManager>(this);
|
||||||
|
popup_manager_->Initialize(); // Registers all popups with PopupID constants
|
||||||
|
|
||||||
|
// STEP 2: Initialize SessionCoordinator (independent of popups)
|
||||||
session_coordinator_ = std::make_unique<SessionCoordinator>(
|
session_coordinator_ = std::make_unique<SessionCoordinator>(
|
||||||
static_cast<void*>(&sessions_), &card_registry_, &toast_manager_);
|
static_cast<void*>(&sessions_), &card_registry_, &toast_manager_);
|
||||||
|
|
||||||
// MenuOrchestrator: Builds all menus and routes actions to appropriate managers
|
// STEP 3: Initialize MenuOrchestrator (depends on popup_manager_, session_coordinator_)
|
||||||
menu_orchestrator_ = std::make_unique<MenuOrchestrator>(
|
menu_orchestrator_ = std::make_unique<MenuOrchestrator>(
|
||||||
this, menu_builder_, rom_file_manager_, project_manager_,
|
this, menu_builder_, rom_file_manager_, project_manager_,
|
||||||
editor_registry_, *session_coordinator_, toast_manager_, *popup_manager_);
|
editor_registry_, *session_coordinator_, toast_manager_, *popup_manager_);
|
||||||
|
|
||||||
// UICoordinator: Coordinates all UI drawing (dialogs, popups, welcome screen)
|
// STEP 4: Initialize UICoordinator (depends on popup_manager_, session_coordinator_)
|
||||||
ui_coordinator_ = std::make_unique<UICoordinator>(
|
ui_coordinator_ = std::make_unique<UICoordinator>(
|
||||||
this, rom_file_manager_, project_manager_, editor_registry_,
|
this, rom_file_manager_, project_manager_, editor_registry_,
|
||||||
*session_coordinator_, window_delegate_, toast_manager_, *popup_manager_,
|
*session_coordinator_, window_delegate_, toast_manager_, *popup_manager_,
|
||||||
shortcut_manager_);
|
shortcut_manager_);
|
||||||
|
|
||||||
|
// STEP 5: ShortcutConfigurator created later in Initialize() method
|
||||||
|
// It depends on all above coordinators being available
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorManager::~EditorManager() = default;
|
EditorManager::~EditorManager() = default;
|
||||||
@@ -227,9 +245,8 @@ void EditorManager::Initialize(gfx::IRenderer* renderer,
|
|||||||
PRINT_IF_ERROR(OpenRomOrProject(filename));
|
PRINT_IF_ERROR(OpenRomOrProject(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize popup manager
|
// Note: PopupManager is now initialized in constructor before MenuOrchestrator
|
||||||
popup_manager_ = std::make_unique<PopupManager>(this);
|
// This ensures all menu callbacks can safely call popup_manager_.Show()
|
||||||
popup_manager_->Initialize();
|
|
||||||
|
|
||||||
// Register emulator cards early (emulator Initialize might not be called)
|
// Register emulator cards early (emulator Initialize might not be called)
|
||||||
// Using EditorCardRegistry directly
|
// Using EditorCardRegistry directly
|
||||||
|
|||||||
@@ -199,18 +199,18 @@ void MenuOrchestrator::AddViewMenuItems() {
|
|||||||
[this]() { OnShowEmulator(); }, "Ctrl+Shift+E")
|
[this]() { OnShowEmulator(); }, "Ctrl+Shift+E")
|
||||||
.Separator();
|
.Separator();
|
||||||
|
|
||||||
|
// Settings and UI
|
||||||
|
menu_builder_
|
||||||
|
.Item("Display Settings", ICON_MD_DISPLAY_SETTINGS,
|
||||||
|
[this]() { OnShowDisplaySettings(); })
|
||||||
|
.Separator();
|
||||||
|
|
||||||
// Additional UI Elements
|
// Additional UI Elements
|
||||||
menu_builder_
|
menu_builder_
|
||||||
.Item("Card Browser", ICON_MD_DASHBOARD,
|
.Item("Card Browser", ICON_MD_DASHBOARD,
|
||||||
[this]() { OnShowCardBrowser(); }, "Ctrl+Shift+B")
|
[this]() { OnShowCardBrowser(); }, "Ctrl+Shift+B")
|
||||||
.Item("Welcome Screen", ICON_MD_HOME,
|
.Item("Welcome Screen", ICON_MD_HOME,
|
||||||
[this]() { OnShowWelcomeScreen(); })
|
[this]() { OnShowWelcomeScreen(); });
|
||||||
.Separator();
|
|
||||||
|
|
||||||
// Display Settings
|
|
||||||
menu_builder_
|
|
||||||
.Item("Display Settings", ICON_MD_DISPLAY_SETTINGS,
|
|
||||||
[this]() { OnShowDisplaySettings(); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::BuildToolsMenu() {
|
void MenuOrchestrator::BuildToolsMenu() {
|
||||||
@@ -401,8 +401,7 @@ void MenuOrchestrator::OnSaveRom() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnSaveRomAs() {
|
void MenuOrchestrator::OnSaveRomAs() {
|
||||||
// TODO: Show save dialog and delegate to rom_manager_
|
popup_manager_.Show(PopupID::kSaveAs);
|
||||||
toast_manager_.Show("Save ROM As", ToastType::kInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnCreateProject() {
|
void MenuOrchestrator::OnCreateProject() {
|
||||||
@@ -552,12 +551,7 @@ void MenuOrchestrator::OnShowEditorSelection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnShowDisplaySettings() {
|
void MenuOrchestrator::OnShowDisplaySettings() {
|
||||||
// Delegate to UICoordinator for display settings popup
|
popup_manager_.Show(PopupID::kDisplaySettings);
|
||||||
if (editor_manager_) {
|
|
||||||
if (auto* ui = editor_manager_->ui_coordinator()) {
|
|
||||||
ui->ShowDisplaySettings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnShowHexEditor() {
|
void MenuOrchestrator::OnShowHexEditor() {
|
||||||
@@ -785,44 +779,44 @@ void MenuOrchestrator::OnShowNetworkStatus() {
|
|||||||
|
|
||||||
// Help menu actions
|
// Help menu actions
|
||||||
void MenuOrchestrator::OnShowAbout() {
|
void MenuOrchestrator::OnShowAbout() {
|
||||||
popup_manager_.Show("About");
|
popup_manager_.Show(PopupID::kAbout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnShowGettingStarted() {
|
void MenuOrchestrator::OnShowGettingStarted() {
|
||||||
popup_manager_.Show("Getting Started");
|
popup_manager_.Show(PopupID::kGettingStarted);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnShowAsarIntegration() {
|
void MenuOrchestrator::OnShowAsarIntegration() {
|
||||||
popup_manager_.Show("Asar Integration");
|
popup_manager_.Show(PopupID::kAsarIntegration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnShowBuildInstructions() {
|
void MenuOrchestrator::OnShowBuildInstructions() {
|
||||||
popup_manager_.Show("Build Instructions");
|
popup_manager_.Show(PopupID::kBuildInstructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnShowCLIUsage() {
|
void MenuOrchestrator::OnShowCLIUsage() {
|
||||||
popup_manager_.Show("CLI Usage");
|
popup_manager_.Show(PopupID::kCLIUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnShowTroubleshooting() {
|
void MenuOrchestrator::OnShowTroubleshooting() {
|
||||||
popup_manager_.Show("Troubleshooting");
|
popup_manager_.Show(PopupID::kTroubleshooting);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnShowContributing() {
|
void MenuOrchestrator::OnShowContributing() {
|
||||||
popup_manager_.Show("Contributing");
|
popup_manager_.Show(PopupID::kContributing);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnShowWhatsNew() {
|
void MenuOrchestrator::OnShowWhatsNew() {
|
||||||
popup_manager_.Show("Whats New v03");
|
popup_manager_.Show(PopupID::kWhatsNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnShowSupportedFeatures() {
|
void MenuOrchestrator::OnShowSupportedFeatures() {
|
||||||
popup_manager_.Show("Supported Features");
|
popup_manager_.Show(PopupID::kSupportedFeatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional File menu actions
|
// Additional File menu actions
|
||||||
void MenuOrchestrator::OnShowRomInfo() {
|
void MenuOrchestrator::OnShowRomInfo() {
|
||||||
popup_manager_.Show("ROM Information");
|
popup_manager_.Show(PopupID::kRomInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnCreateBackup() {
|
void MenuOrchestrator::OnCreateBackup() {
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ class MenuOrchestrator {
|
|||||||
// Editor-specific menu actions
|
// Editor-specific menu actions
|
||||||
void OnSwitchToEditor(EditorType editor_type);
|
void OnSwitchToEditor(EditorType editor_type);
|
||||||
void OnShowEditorSelection();
|
void OnShowEditorSelection();
|
||||||
void OnShowDisplaySettings();
|
void OnShowDisplaySettings(); // Display settings popup
|
||||||
void OnShowHexEditor();
|
void OnShowHexEditor();
|
||||||
void OnShowEmulator();
|
void OnShowEmulator();
|
||||||
void OnShowCardBrowser();
|
void OnShowCardBrowser();
|
||||||
|
|||||||
@@ -16,31 +16,104 @@ PopupManager::PopupManager(EditorManager* editor_manager)
|
|||||||
: editor_manager_(editor_manager), status_(absl::OkStatus()) {}
|
: editor_manager_(editor_manager), status_(absl::OkStatus()) {}
|
||||||
|
|
||||||
void PopupManager::Initialize() {
|
void PopupManager::Initialize() {
|
||||||
// Register all popups
|
// ============================================================================
|
||||||
popups_["About"] = {"About", false, [this]() { DrawAboutPopup(); }};
|
// POPUP REGISTRATION
|
||||||
popups_["ROM Information"] = {"ROM Information", false, [this]() { DrawRomInfoPopup(); }};
|
// ============================================================================
|
||||||
popups_["Save As.."] = {"Save As..", false, [this]() { DrawSaveAsPopup(); }};
|
// All popups must be registered here BEFORE any menu callbacks can trigger them.
|
||||||
popups_["New Project"] = {"New Project", false, [this]() { DrawNewProjectPopup(); }};
|
// This method is called in EditorManager constructor BEFORE MenuOrchestrator
|
||||||
popups_["Supported Features"] = {"Supported Features", false, [this]() { DrawSupportedFeaturesPopup(); }};
|
// and UICoordinator are created, ensuring safe initialization order.
|
||||||
popups_["Open a ROM"] = {"Open a ROM", false, [this]() { DrawOpenRomHelpPopup(); }};
|
//
|
||||||
popups_["Manage Project"] = {"Manage Project", false, [this]() { DrawManageProjectPopup(); }};
|
// Popup Registration Format:
|
||||||
|
// popups_[PopupID::kConstant] = {
|
||||||
|
// .name = PopupID::kConstant,
|
||||||
|
// .type = PopupType::kXxx,
|
||||||
|
// .is_visible = false,
|
||||||
|
// .allow_resize = false/true,
|
||||||
|
// .draw_function = [this]() { DrawXxxPopup(); }
|
||||||
|
// };
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
// v0.3 Help Documentation popups
|
// File Operations
|
||||||
popups_["Getting Started"] = {"Getting Started", false, [this]() { DrawGettingStartedPopup(); }};
|
popups_[PopupID::kSaveAs] = {
|
||||||
popups_["Asar Integration"] = {"Asar Integration", false, [this]() { DrawAsarIntegrationPopup(); }};
|
PopupID::kSaveAs, PopupType::kFileOperation, false, false,
|
||||||
popups_["Build Instructions"] = {"Build Instructions", false, [this]() { DrawBuildInstructionsPopup(); }};
|
[this]() { DrawSaveAsPopup(); }
|
||||||
popups_["CLI Usage"] = {"CLI Usage", false, [this]() { DrawCLIUsagePopup(); }};
|
};
|
||||||
popups_["Troubleshooting"] = {"Troubleshooting", false, [this]() { DrawTroubleshootingPopup(); }};
|
popups_[PopupID::kNewProject] = {
|
||||||
popups_["Contributing"] = {"Contributing", false, [this]() { DrawContributingPopup(); }};
|
PopupID::kNewProject, PopupType::kFileOperation, false, false,
|
||||||
popups_["Whats New v03"] = {"What's New in v0.3", false, [this]() { DrawWhatsNewPopup(); }};
|
[this]() { DrawNewProjectPopup(); }
|
||||||
|
};
|
||||||
|
popups_[PopupID::kManageProject] = {
|
||||||
|
PopupID::kManageProject, PopupType::kFileOperation, false, false,
|
||||||
|
[this]() { DrawManageProjectPopup(); }
|
||||||
|
};
|
||||||
|
|
||||||
// Workspace-related popups
|
// Information
|
||||||
popups_["Workspace Help"] = {"Workspace Help", false, [this]() { DrawWorkspaceHelpPopup(); }};
|
popups_[PopupID::kAbout] = {
|
||||||
popups_["Session Limit Warning"] = {"Session Limit Warning", false, [this]() { DrawSessionLimitWarningPopup(); }};
|
PopupID::kAbout, PopupType::kInfo, false, false,
|
||||||
popups_["Layout Reset Confirm"] = {"Reset Layout Confirmation", false, [this]() { DrawLayoutResetConfirmPopup(); }};
|
[this]() { DrawAboutPopup(); }
|
||||||
|
};
|
||||||
|
popups_[PopupID::kRomInfo] = {
|
||||||
|
PopupID::kRomInfo, PopupType::kInfo, false, false,
|
||||||
|
[this]() { DrawRomInfoPopup(); }
|
||||||
|
};
|
||||||
|
popups_[PopupID::kSupportedFeatures] = {
|
||||||
|
PopupID::kSupportedFeatures, PopupType::kInfo, false, false,
|
||||||
|
[this]() { DrawSupportedFeaturesPopup(); }
|
||||||
|
};
|
||||||
|
popups_[PopupID::kOpenRomHelp] = {
|
||||||
|
PopupID::kOpenRomHelp, PopupType::kHelp, false, false,
|
||||||
|
[this]() { DrawOpenRomHelpPopup(); }
|
||||||
|
};
|
||||||
|
|
||||||
// Settings popups (accessible without ROM)
|
// Help Documentation
|
||||||
popups_["Display Settings"] = {"Display Settings", false, [this]() { DrawDisplaySettingsPopup(); }};
|
popups_[PopupID::kGettingStarted] = {
|
||||||
|
PopupID::kGettingStarted, PopupType::kHelp, false, false,
|
||||||
|
[this]() { DrawGettingStartedPopup(); }
|
||||||
|
};
|
||||||
|
popups_[PopupID::kAsarIntegration] = {
|
||||||
|
PopupID::kAsarIntegration, PopupType::kHelp, false, false,
|
||||||
|
[this]() { DrawAsarIntegrationPopup(); }
|
||||||
|
};
|
||||||
|
popups_[PopupID::kBuildInstructions] = {
|
||||||
|
PopupID::kBuildInstructions, PopupType::kHelp, false, false,
|
||||||
|
[this]() { DrawBuildInstructionsPopup(); }
|
||||||
|
};
|
||||||
|
popups_[PopupID::kCLIUsage] = {
|
||||||
|
PopupID::kCLIUsage, PopupType::kHelp, false, false,
|
||||||
|
[this]() { DrawCLIUsagePopup(); }
|
||||||
|
};
|
||||||
|
popups_[PopupID::kTroubleshooting] = {
|
||||||
|
PopupID::kTroubleshooting, PopupType::kHelp, false, false,
|
||||||
|
[this]() { DrawTroubleshootingPopup(); }
|
||||||
|
};
|
||||||
|
popups_[PopupID::kContributing] = {
|
||||||
|
PopupID::kContributing, PopupType::kHelp, false, false,
|
||||||
|
[this]() { DrawContributingPopup(); }
|
||||||
|
};
|
||||||
|
popups_[PopupID::kWhatsNew] = {
|
||||||
|
PopupID::kWhatsNew, PopupType::kHelp, false, false,
|
||||||
|
[this]() { DrawWhatsNewPopup(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
popups_[PopupID::kDisplaySettings] = {
|
||||||
|
PopupID::kDisplaySettings, PopupType::kSettings, false, true, // Resizable
|
||||||
|
[this]() { DrawDisplaySettingsPopup(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Workspace
|
||||||
|
popups_[PopupID::kWorkspaceHelp] = {
|
||||||
|
PopupID::kWorkspaceHelp, PopupType::kHelp, false, false,
|
||||||
|
[this]() { DrawWorkspaceHelpPopup(); }
|
||||||
|
};
|
||||||
|
popups_[PopupID::kSessionLimitWarning] = {
|
||||||
|
PopupID::kSessionLimitWarning, PopupType::kWarning, false, false,
|
||||||
|
[this]() { DrawSessionLimitWarningPopup(); }
|
||||||
|
};
|
||||||
|
popups_[PopupID::kLayoutResetConfirm] = {
|
||||||
|
PopupID::kLayoutResetConfirm, PopupType::kConfirmation, false, false,
|
||||||
|
[this]() { DrawLayoutResetConfirmPopup(); }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopupManager::DrawPopups() {
|
void PopupManager::DrawPopups() {
|
||||||
@@ -52,11 +125,9 @@ void PopupManager::DrawPopups() {
|
|||||||
if (params.is_visible) {
|
if (params.is_visible) {
|
||||||
OpenPopup(name.c_str());
|
OpenPopup(name.c_str());
|
||||||
|
|
||||||
// Special handling for Display Settings popup to make it resizable
|
// Use allow_resize flag from popup definition
|
||||||
ImGuiWindowFlags popup_flags = ImGuiWindowFlags_AlwaysAutoResize;
|
ImGuiWindowFlags popup_flags = params.allow_resize ?
|
||||||
if (name == "Display Settings") {
|
ImGuiWindowFlags_None : ImGuiWindowFlags_AlwaysAutoResize;
|
||||||
popup_flags = ImGuiWindowFlags_None; // Allow resizing for display settings
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BeginPopupModal(name.c_str(), nullptr, popup_flags)) {
|
if (BeginPopupModal(name.c_str(), nullptr, popup_flags)) {
|
||||||
params.draw_function();
|
params.draw_function();
|
||||||
@@ -67,14 +138,31 @@ void PopupManager::DrawPopups() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PopupManager::Show(const char* name) {
|
void PopupManager::Show(const char* name) {
|
||||||
auto it = popups_.find(name);
|
if (!name) {
|
||||||
|
return; // Safety check for null pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name_str(name);
|
||||||
|
auto it = popups_.find(name_str);
|
||||||
if (it != popups_.end()) {
|
if (it != popups_.end()) {
|
||||||
it->second.is_visible = true;
|
it->second.is_visible = true;
|
||||||
|
} else {
|
||||||
|
// Log warning for unregistered popup
|
||||||
|
printf("[PopupManager] Warning: Popup '%s' not registered. Available popups: ", name);
|
||||||
|
for (const auto& [key, _] : popups_) {
|
||||||
|
printf("'%s' ", key.c_str());
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopupManager::Hide(const char* name) {
|
void PopupManager::Hide(const char* name) {
|
||||||
auto it = popups_.find(name);
|
if (!name) {
|
||||||
|
return; // Safety check for null pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name_str(name);
|
||||||
|
auto it = popups_.find(name_str);
|
||||||
if (it != popups_.end()) {
|
if (it != popups_.end()) {
|
||||||
it->second.is_visible = false;
|
it->second.is_visible = false;
|
||||||
CloseCurrentPopup();
|
CloseCurrentPopup();
|
||||||
@@ -82,7 +170,12 @@ void PopupManager::Hide(const char* name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PopupManager::IsVisible(const char* name) const {
|
bool PopupManager::IsVisible(const char* name) const {
|
||||||
auto it = popups_.find(name);
|
if (!name) {
|
||||||
|
return false; // Safety check for null pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name_str(name);
|
||||||
|
auto it = popups_.find(name_str);
|
||||||
if (it != popups_.end()) {
|
if (it != popups_.end()) {
|
||||||
return it->second.is_visible;
|
return it->second.is_visible;
|
||||||
}
|
}
|
||||||
@@ -189,7 +282,7 @@ void PopupManager::DrawSaveAsPopup() {
|
|||||||
auto status = editor_manager_->SaveRomAs(final_filename);
|
auto status = editor_manager_->SaveRomAs(final_filename);
|
||||||
if (status.ok()) {
|
if (status.ok()) {
|
||||||
save_as_filename = "";
|
save_as_filename = "";
|
||||||
Hide("Save As..");
|
Hide(PopupID::kSaveAs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,7 +291,7 @@ void PopupManager::DrawSaveAsPopup() {
|
|||||||
if (Button(absl::StrFormat("%s Cancel", ICON_MD_CANCEL).c_str(),
|
if (Button(absl::StrFormat("%s Cancel", ICON_MD_CANCEL).c_str(),
|
||||||
gui::kDefaultModalSize)) {
|
gui::kDefaultModalSize)) {
|
||||||
save_as_filename = "";
|
save_as_filename = "";
|
||||||
Hide("Save As..");
|
Hide(PopupID::kSaveAs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +358,7 @@ void PopupManager::DrawNewProjectPopup() {
|
|||||||
rom_filename = "";
|
rom_filename = "";
|
||||||
labels_filename = "";
|
labels_filename = "";
|
||||||
code_folder = "";
|
code_folder = "";
|
||||||
Hide("New Project");
|
Hide(PopupID::kNewProject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,7 +371,7 @@ void PopupManager::DrawNewProjectPopup() {
|
|||||||
rom_filename = "";
|
rom_filename = "";
|
||||||
labels_filename = "";
|
labels_filename = "";
|
||||||
code_folder = "";
|
code_folder = "";
|
||||||
Hide("New Project");
|
Hide(PopupID::kNewProject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,12 +13,84 @@ namespace editor {
|
|||||||
// Forward declaration
|
// Forward declaration
|
||||||
class EditorManager;
|
class EditorManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum PopupType
|
||||||
|
* @brief Type classification for popups to enable future filtering and organization
|
||||||
|
*/
|
||||||
|
enum class PopupType {
|
||||||
|
kInfo, // Information display (About, ROM Info, etc.)
|
||||||
|
kHelp, // Help documentation (Getting Started, etc.)
|
||||||
|
kSettings, // Settings dialogs (Display Settings, etc.)
|
||||||
|
kFileOperation, // File operations (Save As, New Project, etc.)
|
||||||
|
kConfirmation, // Confirmation dialogs (Layout Reset, etc.)
|
||||||
|
kWarning, // Warning messages (Session Limit, etc.)
|
||||||
|
kEditor // Editor-specific dialogs
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct PopupDefinition
|
||||||
|
* @brief Complete definition of a popup including metadata
|
||||||
|
*/
|
||||||
|
struct PopupDefinition {
|
||||||
|
const char* id; // Unique constant identifier
|
||||||
|
const char* display_name; // Human-readable name for UI
|
||||||
|
PopupType type; // Type classification
|
||||||
|
bool allow_resize; // Whether popup can be resized
|
||||||
|
std::function<void()> draw_function; // Drawing callback (set at runtime)
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct PopupParams
|
||||||
|
* @brief Runtime state for a registered popup
|
||||||
|
*/
|
||||||
struct PopupParams {
|
struct PopupParams {
|
||||||
std::string name;
|
std::string name;
|
||||||
|
PopupType type;
|
||||||
bool is_visible = false;
|
bool is_visible = false;
|
||||||
|
bool allow_resize = false;
|
||||||
std::function<void()> draw_function;
|
std::function<void()> draw_function;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @namespace PopupID
|
||||||
|
* @brief String constants for all popup identifiers to prevent typos
|
||||||
|
*/
|
||||||
|
namespace PopupID {
|
||||||
|
// File Operations
|
||||||
|
constexpr const char* kSaveAs = "Save As..";
|
||||||
|
constexpr const char* kNewProject = "New Project";
|
||||||
|
constexpr const char* kManageProject = "Manage Project";
|
||||||
|
|
||||||
|
// Information
|
||||||
|
constexpr const char* kAbout = "About";
|
||||||
|
constexpr const char* kRomInfo = "ROM Information";
|
||||||
|
constexpr const char* kSupportedFeatures = "Supported Features";
|
||||||
|
constexpr const char* kStatus = "Status";
|
||||||
|
|
||||||
|
// Help Documentation
|
||||||
|
constexpr const char* kGettingStarted = "Getting Started";
|
||||||
|
constexpr const char* kAsarIntegration = "Asar Integration";
|
||||||
|
constexpr const char* kBuildInstructions = "Build Instructions";
|
||||||
|
constexpr const char* kCLIUsage = "CLI Usage";
|
||||||
|
constexpr const char* kTroubleshooting = "Troubleshooting";
|
||||||
|
constexpr const char* kContributing = "Contributing";
|
||||||
|
constexpr const char* kWhatsNew = "Whats New v03";
|
||||||
|
constexpr const char* kOpenRomHelp = "Open a ROM";
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
constexpr const char* kDisplaySettings = "Display Settings";
|
||||||
|
|
||||||
|
// Workspace
|
||||||
|
constexpr const char* kWorkspaceHelp = "Workspace Help";
|
||||||
|
constexpr const char* kSessionLimitWarning = "Session Limit Warning";
|
||||||
|
constexpr const char* kLayoutResetConfirm = "Reset Layout Confirmation";
|
||||||
|
|
||||||
|
// Future expansion
|
||||||
|
constexpr const char* kQuickExport = "Quick Export";
|
||||||
|
constexpr const char* kAssetImport = "Asset Import";
|
||||||
|
constexpr const char* kScriptGenerator = "Script Generator";
|
||||||
|
}
|
||||||
|
|
||||||
// ImGui popup manager.
|
// ImGui popup manager.
|
||||||
class PopupManager {
|
class PopupManager {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ void UICoordinator::DrawAllUI() {
|
|||||||
// Draw all UI components in order
|
// Draw all UI components in order
|
||||||
DrawMenuBarExtras();
|
DrawMenuBarExtras();
|
||||||
DrawContextSensitiveCardControl();
|
DrawContextSensitiveCardControl();
|
||||||
|
DrawCommandPalette(); // NEW: Moved from EditorManager
|
||||||
DrawSessionSwitcher();
|
DrawSessionSwitcher();
|
||||||
DrawSessionManager();
|
DrawSessionManager();
|
||||||
DrawSessionRenameDialog();
|
DrawSessionRenameDialog();
|
||||||
@@ -119,15 +120,15 @@ void UICoordinator::DrawAllUI() {
|
|||||||
void UICoordinator::DrawMenuBarExtras() {
|
void UICoordinator::DrawMenuBarExtras() {
|
||||||
// Get current ROM from EditorManager (RomFileManager doesn't track "current")
|
// Get current ROM from EditorManager (RomFileManager doesn't track "current")
|
||||||
auto* current_rom = editor_manager_->GetCurrentRom();
|
auto* current_rom = editor_manager_->GetCurrentRom();
|
||||||
|
|
||||||
|
// Calculate version width for right alignment
|
||||||
std::string version_text = absl::StrFormat("v%s", editor_manager_->version().c_str());
|
std::string version_text = absl::StrFormat("v%s", editor_manager_->version().c_str());
|
||||||
float version_width = ImGui::CalcTextSize(version_text.c_str()).x;
|
float version_width = ImGui::CalcTextSize(version_text.c_str()).x;
|
||||||
float session_rom_area_width = 280.0f;
|
|
||||||
|
|
||||||
ImGui::SameLine(ImGui::GetWindowWidth() - version_width - 10 - session_rom_area_width);
|
|
||||||
|
|
||||||
// Session indicator with Material Design styling
|
// Session indicator with Material Design styling
|
||||||
if (session_coordinator_.HasMultipleSessions()) {
|
if (session_coordinator_.HasMultipleSessions()) {
|
||||||
std::string session_button_text = absl::StrFormat("%s%zu", ICON_MD_TAB,
|
ImGui::SameLine();
|
||||||
|
std::string session_button_text = absl::StrFormat("%s %zu", ICON_MD_TAB,
|
||||||
session_coordinator_.GetActiveSessionCount());
|
session_coordinator_.GetActiveSessionCount());
|
||||||
|
|
||||||
// Material Design button styling
|
// Material Design button styling
|
||||||
@@ -142,21 +143,32 @@ void UICoordinator::DrawMenuBarExtras() {
|
|||||||
ImGui::PopStyleColor(3);
|
ImGui::PopStyleColor(3);
|
||||||
|
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::SetTooltip("Sessions: %zu active\nClick to switch",
|
ImGui::SetTooltip("Switch Sessions (Ctrl+Tab)");
|
||||||
session_coordinator_.GetActiveSessionCount());
|
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ROM information display with Material Design card styling
|
// ROM information display with Material Design card styling
|
||||||
|
ImGui::SameLine();
|
||||||
if (current_rom && current_rom->is_loaded()) {
|
if (current_rom && current_rom->is_loaded()) {
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, gui::GetTextSecondaryVec4());
|
ImGui::PushStyleColor(ImGuiCol_Text, gui::GetTextSecondaryVec4());
|
||||||
ImGui::Text("%s %s", ICON_MD_INSERT_DRIVE_FILE, current_rom->title().c_str());
|
std::string rom_title = current_rom->title();
|
||||||
|
if (current_rom->dirty()) {
|
||||||
|
ImGui::Text("%s %s*", ICON_MD_CIRCLE, rom_title.c_str());
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("Unsaved changes");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::Text("%s %s", ICON_MD_INSERT_DRIVE_FILE, rom_title.c_str());
|
||||||
|
}
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
} else {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, gui::GetTextDisabledVec4());
|
||||||
|
ImGui::Text("%s No ROM", ICON_MD_WARNING);
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
ImGui::SameLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version info with subtle styling
|
// Version info aligned to far right
|
||||||
|
ImGui::SameLine(ImGui::GetWindowWidth() - version_width - 15.0f);
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, gui::GetTextDisabledVec4());
|
ImGui::PushStyleColor(ImGuiCol_Text, gui::GetTextDisabledVec4());
|
||||||
ImGui::Text("%s", version_text.c_str());
|
ImGui::Text("%s", version_text.c_str());
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
@@ -319,8 +331,9 @@ void UICoordinator::HidePopup(const std::string& popup_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UICoordinator::ShowDisplaySettings() {
|
void UICoordinator::ShowDisplaySettings() {
|
||||||
show_display_settings_ = true;
|
// Display Settings is now a popup managed by PopupManager
|
||||||
ShowPopup("Display Settings");
|
// Delegate directly to PopupManager instead of UICoordinator
|
||||||
|
popup_manager_.Show(PopupID::kDisplaySettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UICoordinator::HideCurrentEditorCards() {
|
void UICoordinator::HideCurrentEditorCards() {
|
||||||
|
|||||||
Reference in New Issue
Block a user