#include "Composition/EditorWindowWorkspaceStore.h" #include #include namespace XCEngine::UI::Editor::App::Internal { namespace { UIEditorWindowWorkspaceState BuildWindowState( std::string_view windowId, const UIEditorWorkspaceController& workspaceController) { UIEditorWindowWorkspaceState state = {}; state.windowId = std::string(windowId); state.workspace = workspaceController.GetWorkspace(); state.session = workspaceController.GetSession(); return state; } std::string ResolveFallbackWindowId(const UIEditorWindowWorkspaceSet& windowSet) { if (!windowSet.primaryWindowId.empty() && FindUIEditorWindowWorkspaceState(windowSet, windowSet.primaryWindowId) != nullptr) { return windowSet.primaryWindowId; } return windowSet.windows.empty() ? std::string() : windowSet.windows.front().windowId; } void UpsertWindowState( UIEditorWindowWorkspaceSet& windowSet, UIEditorWindowWorkspaceState windowState) { if (UIEditorWindowWorkspaceState* existing = FindMutableUIEditorWindowWorkspaceState(windowSet, windowState.windowId); existing != nullptr) { *existing = std::move(windowState); return; } windowSet.windows.push_back(std::move(windowState)); } } // namespace EditorWindowWorkspaceStore::EditorWindowWorkspaceStore(UIEditorPanelRegistry panelRegistry) : m_panelRegistry(std::move(panelRegistry)) {} UIEditorWindowWorkspaceController EditorWindowWorkspaceStore::BuildMutationController() const { return UIEditorWindowWorkspaceController(m_panelRegistry, m_windowSet); } bool EditorWindowWorkspaceStore::RegisterWindowProjection( std::string_view windowId, bool primary, const UIEditorWorkspaceController& workspaceController, std::string& outError) { UIEditorWindowWorkspaceSet nextWindowSet = m_windowSet; UpsertWindowState(nextWindowSet, BuildWindowState(windowId, workspaceController)); if (primary) { if (!nextWindowSet.primaryWindowId.empty() && nextWindowSet.primaryWindowId != windowId) { outError = "Cannot register a second primary window '" + std::string(windowId) + "' while '" + nextWindowSet.primaryWindowId + "' is still primary."; return false; } nextWindowSet.primaryWindowId = std::string(windowId); } else if (nextWindowSet.primaryWindowId.empty()) { outError = "Cannot register detached window '" + std::string(windowId) + "' before the primary window exists."; return false; } if (nextWindowSet.activeWindowId.empty() || FindUIEditorWindowWorkspaceState(nextWindowSet, nextWindowSet.activeWindowId) == nullptr) { nextWindowSet.activeWindowId = ResolveFallbackWindowId(nextWindowSet); } if (!ValidateWindowSet(nextWindowSet, outError)) { return false; } ReplaceWindowSet(std::move(nextWindowSet)); outError.clear(); return true; } bool EditorWindowWorkspaceStore::CommitWindowProjection( std::string_view windowId, const UIEditorWorkspaceController& workspaceController, std::string& outError) { UIEditorWindowWorkspaceSet nextWindowSet = m_windowSet; UIEditorWindowWorkspaceState* existingWindow = FindMutableUIEditorWindowWorkspaceState(nextWindowSet, windowId); if (existingWindow == nullptr) { outError = "Window '" + std::string(windowId) + "' is not registered in the workspace store."; return false; } existingWindow->workspace = workspaceController.GetWorkspace(); existingWindow->session = workspaceController.GetSession(); if (nextWindowSet.activeWindowId.empty() || FindUIEditorWindowWorkspaceState(nextWindowSet, nextWindowSet.activeWindowId) == nullptr) { nextWindowSet.activeWindowId = ResolveFallbackWindowId(nextWindowSet); } if (!ValidateWindowSet(nextWindowSet, outError)) { return false; } ReplaceWindowSet(std::move(nextWindowSet)); outError.clear(); return true; } bool EditorWindowWorkspaceStore::ValidateWindowSet( const UIEditorWindowWorkspaceSet& windowSet, std::string& outError) const { const UIEditorWindowWorkspaceValidationResult validation = ValidateUIEditorWindowWorkspaceSet(m_panelRegistry, windowSet); if (!validation.IsValid()) { outError = validation.message; return false; } outError.clear(); return true; } void EditorWindowWorkspaceStore::ReplaceWindowSet(UIEditorWindowWorkspaceSet windowSet) { m_windowSet = std::move(windowSet); } void EditorWindowWorkspaceStore::RemoveWindow(std::string_view windowId, bool primary) { if (m_windowSet.windows.empty()) { return; } if (primary || m_windowSet.primaryWindowId == windowId) { m_windowSet = {}; return; } m_windowSet.windows.erase( std::remove_if( m_windowSet.windows.begin(), m_windowSet.windows.end(), [windowId](const UIEditorWindowWorkspaceState& state) { return state.windowId == windowId; }), m_windowSet.windows.end()); if (m_windowSet.windows.empty()) { m_windowSet = {}; return; } if (FindUIEditorWindowWorkspaceState(m_windowSet, m_windowSet.primaryWindowId) == nullptr) { m_windowSet.primaryWindowId = ResolveFallbackWindowId(m_windowSet); } if (m_windowSet.activeWindowId == windowId || FindUIEditorWindowWorkspaceState(m_windowSet, m_windowSet.activeWindowId) == nullptr) { m_windowSet.activeWindowId = ResolveFallbackWindowId(m_windowSet); } } } // namespace XCEngine::UI::Editor::App::Internal