170 lines
5.6 KiB
C++
170 lines
5.6 KiB
C++
#include "Composition/EditorWindowWorkspaceStore.h"
|
|
|
|
#include <algorithm>
|
|
#include <utility>
|
|
|
|
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
|