#include "Workspace/WorkspaceControllerInternal.h" #include namespace XCEngine::UI::Editor::Internal { bool IsPanelOpenAndVisible( const UIEditorWorkspaceSession& session, std::string_view panelId) { const UIEditorPanelSessionState* panelState = FindUIEditorPanelSessionState(session, panelId); return panelState != nullptr && panelState->open && panelState->visible; } std::vector CollectVisiblePanelIds( const UIEditorWorkspaceModel& workspace, const UIEditorWorkspaceSession& session) { const std::vector panels = CollectUIEditorWorkspaceVisiblePanels(workspace, session); std::vector ids = {}; ids.reserve(panels.size()); for (const UIEditorWorkspaceVisiblePanel& panel : panels) { ids.push_back(panel.panelId); } return ids; } VisibleTabStackInfo ResolveVisibleTabStackInfo( const UIEditorWorkspaceNode& node, const UIEditorWorkspaceSession& session, std::string_view panelId) { VisibleTabStackInfo info = {}; for (const UIEditorWorkspaceNode& child : node.children) { if (child.kind != UIEditorWorkspaceNodeKind::Panel) { continue; } const bool visible = IsPanelOpenAndVisible(session, child.panel.panelId); if (child.panel.panelId == panelId) { info.panelExists = true; info.panelVisible = visible; if (visible) { info.currentVisibleIndex = info.visibleTabCount; } } if (visible) { ++info.visibleTabCount; } } return info; } std::size_t CountVisibleTabs( const UIEditorWorkspaceNode& node, const UIEditorWorkspaceSession& session) { if (node.kind != UIEditorWorkspaceNodeKind::TabStack) { return 0u; } std::size_t visibleCount = 0u; for (const UIEditorWorkspaceNode& child : node.children) { if (child.kind == UIEditorWorkspaceNodeKind::Panel && IsPanelOpenAndVisible(session, child.panel.panelId)) { ++visibleCount; } } return visibleCount; } } // namespace XCEngine::UI::Editor::Internal namespace XCEngine::UI::Editor { std::string_view GetUIEditorWorkspaceCommandKindName(UIEditorWorkspaceCommandKind kind) { switch (kind) { case UIEditorWorkspaceCommandKind::OpenPanel: return "OpenPanel"; case UIEditorWorkspaceCommandKind::ClosePanel: return "ClosePanel"; case UIEditorWorkspaceCommandKind::ShowPanel: return "ShowPanel"; case UIEditorWorkspaceCommandKind::HidePanel: return "HidePanel"; case UIEditorWorkspaceCommandKind::ActivatePanel: return "ActivatePanel"; case UIEditorWorkspaceCommandKind::ResetWorkspace: return "ResetWorkspace"; } return "Unknown"; } std::string_view GetUIEditorWorkspaceCommandStatusName( UIEditorWorkspaceCommandStatus status) { switch (status) { case UIEditorWorkspaceCommandStatus::Changed: return "Changed"; case UIEditorWorkspaceCommandStatus::NoOp: return "NoOp"; case UIEditorWorkspaceCommandStatus::Rejected: return "Rejected"; } return "Unknown"; } std::string_view GetUIEditorWorkspaceLayoutOperationStatusName( UIEditorWorkspaceLayoutOperationStatus status) { switch (status) { case UIEditorWorkspaceLayoutOperationStatus::Changed: return "Changed"; case UIEditorWorkspaceLayoutOperationStatus::NoOp: return "NoOp"; case UIEditorWorkspaceLayoutOperationStatus::Rejected: return "Rejected"; } return "Unknown"; } UIEditorWorkspaceController::UIEditorWorkspaceController( UIEditorPanelRegistry panelRegistry, UIEditorWorkspaceModel workspace, UIEditorWorkspaceSession session) : m_panelRegistry(std::move(panelRegistry)) , m_baselineWorkspace(CanonicalizeUIEditorWorkspaceModel(workspace)) , m_baselineSession(session) , m_workspace(m_baselineWorkspace) , m_session(std::move(session)) { } UIEditorWorkspaceControllerValidationResult UIEditorWorkspaceController::ValidateState() const { const UIEditorPanelRegistryValidationResult registryValidation = ValidateUIEditorPanelRegistry(m_panelRegistry); if (!registryValidation.IsValid()) { UIEditorWorkspaceControllerValidationResult result = {}; result.code = UIEditorWorkspaceControllerValidationCode::InvalidPanelRegistry; result.message = registryValidation.message; return result; } const UIEditorWorkspaceValidationResult workspaceValidation = ValidateUIEditorWorkspace(m_workspace); if (!workspaceValidation.IsValid()) { UIEditorWorkspaceControllerValidationResult result = {}; result.code = UIEditorWorkspaceControllerValidationCode::InvalidWorkspace; result.message = workspaceValidation.message; return result; } const UIEditorWorkspaceSessionValidationResult sessionValidation = ValidateUIEditorWorkspaceSession(m_panelRegistry, m_workspace, m_session); if (!sessionValidation.IsValid()) { UIEditorWorkspaceControllerValidationResult result = {}; result.code = UIEditorWorkspaceControllerValidationCode::InvalidWorkspaceSession; result.message = sessionValidation.message; return result; } return {}; } UIEditorWorkspaceLayoutSnapshot UIEditorWorkspaceController::CaptureLayoutSnapshot() const { return BuildUIEditorWorkspaceLayoutSnapshot(m_workspace, m_session); } UIEditorWorkspaceCommandResult UIEditorWorkspaceController::BuildResult( const UIEditorWorkspaceCommand& command, UIEditorWorkspaceCommandStatus status, std::string message) const { UIEditorWorkspaceCommandResult result = {}; result.kind = command.kind; result.status = status; result.panelId = command.panelId; result.message = std::move(message); result.activePanelId = m_workspace.activePanelId; result.visiblePanelIds = Internal::CollectVisiblePanelIds(m_workspace, m_session); return result; } UIEditorWorkspaceLayoutOperationResult UIEditorWorkspaceController::BuildLayoutOperationResult( UIEditorWorkspaceLayoutOperationStatus status, std::string message) const { UIEditorWorkspaceLayoutOperationResult result = {}; result.status = status; result.message = std::move(message); result.activePanelId = m_workspace.activePanelId; result.visiblePanelIds = Internal::CollectVisiblePanelIds(m_workspace, m_session); return result; } UIEditorWorkspaceCommandResult UIEditorWorkspaceController::FinalizeMutation( const UIEditorWorkspaceCommand& command, bool changed, std::string changedMessage, std::string unexpectedFailureMessage, const UIEditorWorkspaceModel& previousWorkspace, const UIEditorWorkspaceSession& previousSession) { if (!changed) { return BuildResult( command, UIEditorWorkspaceCommandStatus::Rejected, std::move(unexpectedFailureMessage)); } const UIEditorWorkspaceControllerValidationResult validation = ValidateState(); if (!validation.IsValid()) { m_workspace = previousWorkspace; m_session = previousSession; return BuildResult( command, UIEditorWorkspaceCommandStatus::Rejected, "Command produced invalid workspace state: " + validation.message); } return BuildResult( command, UIEditorWorkspaceCommandStatus::Changed, std::move(changedMessage)); } const UIEditorPanelDescriptor* UIEditorWorkspaceController::FindPanelDescriptor( std::string_view panelId) const { return FindUIEditorPanelDescriptor(m_panelRegistry, panelId); } UIEditorWorkspaceController BuildDefaultUIEditorWorkspaceController( const UIEditorPanelRegistry& panelRegistry, const UIEditorWorkspaceModel& workspace) { const UIEditorWorkspaceModel canonicalWorkspace = CanonicalizeUIEditorWorkspaceModel(workspace); return UIEditorWorkspaceController( panelRegistry, canonicalWorkspace, BuildDefaultUIEditorWorkspaceSession(panelRegistry, canonicalWorkspace)); } } // namespace XCEngine::UI::Editor