Files
XCEngine/editor/src/Workspace/UIEditorWindowWorkspaceModel.cpp
2026-04-25 16:46:01 +08:00

160 lines
5.6 KiB
C++

#include <XCEditor/Workspace/UIEditorWindowWorkspaceModel.h>
#include <XCEditor/Workspace/UIEditorWorkspaceValidation.h>
#include <unordered_map>
#include <unordered_set>
#include <utility>
namespace XCEngine::UI::Editor {
namespace {
UIEditorWindowWorkspaceValidationResult MakeValidationError(
UIEditorWindowWorkspaceValidationCode code,
std::string message) {
UIEditorWindowWorkspaceValidationResult result = {};
result.code = code;
result.message = std::move(message);
return result;
}
} // namespace
UIEditorWindowWorkspaceSet BuildDefaultUIEditorWindowWorkspaceSet(
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWorkspaceModel& workspace,
std::string primaryWindowId) {
if (primaryWindowId.empty()) {
primaryWindowId = "main-window";
}
UIEditorWindowWorkspaceSet windowSet = {};
windowSet.primaryWindowId = primaryWindowId;
windowSet.activeWindowId = primaryWindowId;
UIEditorWindowWorkspaceState state = {};
state.windowId = primaryWindowId;
state.workspace = CanonicalizeUIEditorWorkspaceModel(workspace);
state.session = BuildDefaultUIEditorWorkspaceSession(panelRegistry, state.workspace);
windowSet.windows.push_back(std::move(state));
return windowSet;
}
const UIEditorWindowWorkspaceState* FindUIEditorWindowWorkspaceState(
const UIEditorWindowWorkspaceSet& windowSet,
std::string_view windowId) {
for (const UIEditorWindowWorkspaceState& state : windowSet.windows) {
if (state.windowId == windowId) {
return &state;
}
}
return nullptr;
}
UIEditorWindowWorkspaceState* FindMutableUIEditorWindowWorkspaceState(
UIEditorWindowWorkspaceSet& windowSet,
std::string_view windowId) {
for (UIEditorWindowWorkspaceState& state : windowSet.windows) {
if (state.windowId == windowId) {
return &state;
}
}
return nullptr;
}
UIEditorWindowWorkspaceValidationResult ValidateUIEditorWindowWorkspaceSet(
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWindowWorkspaceSet& windowSet) {
const UIEditorPanelRegistryValidationResult registryValidation =
ValidateUIEditorPanelRegistry(panelRegistry);
if (!registryValidation.IsValid()) {
return MakeValidationError(
UIEditorWindowWorkspaceValidationCode::InvalidPanelRegistry,
registryValidation.message);
}
if (windowSet.primaryWindowId.empty()) {
return MakeValidationError(
UIEditorWindowWorkspaceValidationCode::MissingPrimaryWindow,
"Primary window id must not be empty.");
}
if (windowSet.activeWindowId.empty()) {
return MakeValidationError(
UIEditorWindowWorkspaceValidationCode::MissingActiveWindow,
"Active window id must not be empty.");
}
std::unordered_set<std::string> seenWindowIds = {};
std::unordered_map<std::string, std::string> panelOwners = {};
bool hasPrimaryWindow = false;
bool hasActiveWindow = false;
for (const UIEditorWindowWorkspaceState& state : windowSet.windows) {
if (state.windowId.empty()) {
return MakeValidationError(
UIEditorWindowWorkspaceValidationCode::EmptyWindowId,
"Window id must not be empty.");
}
if (!seenWindowIds.insert(state.windowId).second) {
return MakeValidationError(
UIEditorWindowWorkspaceValidationCode::DuplicateWindowId,
"Window id '" + state.windowId + "' is duplicated.");
}
if (state.windowId == windowSet.primaryWindowId) {
hasPrimaryWindow = true;
}
if (state.windowId == windowSet.activeWindowId) {
hasActiveWindow = true;
}
const UIEditorWorkspaceValidationResult workspaceValidation =
ValidateUIEditorWorkspace(state.workspace);
if (!workspaceValidation.IsValid()) {
return MakeValidationError(
UIEditorWindowWorkspaceValidationCode::InvalidWorkspace,
"Window '" + state.windowId + "' workspace invalid: " +
workspaceValidation.message);
}
const UIEditorWorkspaceSessionValidationResult sessionValidation =
ValidateUIEditorWorkspaceSession(panelRegistry, state.workspace, state.session);
if (!sessionValidation.IsValid()) {
return MakeValidationError(
UIEditorWindowWorkspaceValidationCode::InvalidSession,
"Window '" + state.windowId + "' session invalid: " +
sessionValidation.message);
}
for (const UIEditorPanelSessionState& panelState : state.session.panelStates) {
const auto [ownerIt, inserted] =
panelOwners.emplace(panelState.panelId, state.windowId);
if (!inserted) {
return MakeValidationError(
UIEditorWindowWorkspaceValidationCode::DuplicatePanelAcrossWindows,
"Panel '" + panelState.panelId + "' is present in both window '" +
ownerIt->second + "' and window '" + state.windowId + "'.");
}
}
}
if (!hasPrimaryWindow) {
return MakeValidationError(
UIEditorWindowWorkspaceValidationCode::MissingPrimaryWindow,
"Primary window '" + windowSet.primaryWindowId + "' does not exist.");
}
if (!hasActiveWindow) {
return MakeValidationError(
UIEditorWindowWorkspaceValidationCode::MissingActiveWindow,
"Active window '" + windowSet.activeWindowId + "' does not exist.");
}
return {};
}
} // namespace XCEngine::UI::Editor