Files
XCEngine/editor/app/Windowing/System/EditorWindowSynchronizationPlanner.cpp

144 lines
5.0 KiB
C++

#include "Windowing/System/EditorWindowSynchronizationPlanner.h"
#include "Windowing/System/EditorWindowPresentationPolicy.h"
#include <XCEditor/Workspace/UIEditorWorkspaceLayoutPersistence.h>
#include <algorithm>
namespace XCEngine::UI::Editor::App {
namespace {
const EditorWindowHostSnapshot* FindHostWindowSnapshot(
const std::vector<EditorWindowHostSnapshot>& hostWindows,
std::string_view windowId) {
const auto it = std::find_if(
hostWindows.begin(),
hostWindows.end(),
[windowId](const EditorWindowHostSnapshot& snapshot) {
return snapshot.windowId == windowId;
});
return it != hostWindows.end() ? &(*it) : nullptr;
}
bool AreWindowWorkspaceStatesEquivalent(
const UIEditorWindowWorkspaceState& lhs,
const UIEditorWindowWorkspaceState& rhs) {
if (lhs.windowId != rhs.windowId) {
return false;
}
return AreUIEditorWorkspaceLayoutSnapshotsEquivalent(
BuildUIEditorWorkspaceLayoutSnapshot(lhs.workspace, lhs.session),
BuildUIEditorWorkspaceLayoutSnapshot(rhs.workspace, rhs.session));
}
} // namespace
EditorWindowSynchronizationPlan EditorWindowSynchronizationPlanner::Build(
const EditorWindowSynchronizationPlannerInput& input) {
EditorWindowSynchronizationPlan plan = {};
if (input.panelRegistry == nullptr) {
plan.errorMessage = "window synchronization planner missing panel registry";
return plan;
}
if (input.targetWindowSet == nullptr) {
plan.errorMessage = "window synchronization planner missing target window set";
return plan;
}
plan.valid = true;
plan.targetWindowSet = *input.targetWindowSet;
plan.actions.reserve(
input.targetWindowSet->windows.size() + input.hostWindows.size());
for (const UIEditorWindowWorkspaceState& targetWindowState :
input.targetWindowSet->windows) {
const bool primary = targetWindowState.windowId ==
input.targetWindowSet->primaryWindowId;
const std::wstring title = ResolveEditorWindowPresentationTitle(
input.primaryWindowTitle,
*input.panelRegistry,
targetWindowState,
primary);
const EditorWindowHostSnapshot* const existingSnapshot =
FindHostWindowSnapshot(input.hostWindows, targetWindowState.windowId);
if (existingSnapshot == nullptr) {
EditorWindowSynchronizationAction action = {};
action.kind = EditorWindowSynchronizationActionKind::CreateWorkspaceWindow;
action.create.windowState = targetWindowState;
action.create.primary = primary;
action.create.title = title;
if (!input.preferredNewWindowId.empty() &&
targetWindowState.windowId == input.preferredNewWindowId) {
action.create.placement = input.preferredPlacement;
}
plan.actions.push_back(std::move(action));
continue;
}
if (!existingSnapshot->workspaceWindow) {
plan.valid = false;
plan.errorMessage =
"workspace synchronization rejected: window '" +
targetWindowState.windowId + "' is not a workspace window";
plan.actions.clear();
return plan;
}
if (!existingSnapshot->running) {
plan.valid = false;
plan.errorMessage =
"workspace synchronization rejected: window '" +
targetWindowState.windowId + "' is not running";
plan.actions.clear();
return plan;
}
const bool needsUpdate =
!existingSnapshot->hasWorkspaceProjection ||
!AreWindowWorkspaceStatesEquivalent(
existingSnapshot->workspaceState,
targetWindowState) ||
existingSnapshot->primary != primary ||
existingSnapshot->title != title;
if (!needsUpdate) {
continue;
}
EditorWindowSynchronizationAction action = {};
action.kind = EditorWindowSynchronizationActionKind::UpdateWorkspaceWindow;
action.update.windowState = targetWindowState;
action.update.primary = primary;
action.update.title = title;
plan.actions.push_back(std::move(action));
}
for (const EditorWindowHostSnapshot& snapshot : input.hostWindows) {
if (!snapshot.workspaceWindow ||
!snapshot.hasNativeWindow ||
!snapshot.running ||
snapshot.primary) {
continue;
}
const bool existsInTarget =
FindUIEditorWindowWorkspaceState(*input.targetWindowSet, snapshot.windowId) != nullptr;
if (existsInTarget) {
continue;
}
EditorWindowSynchronizationAction action = {};
action.kind = EditorWindowSynchronizationActionKind::CloseWorkspaceWindow;
action.close.windowId = snapshot.windowId;
plan.actions.push_back(std::move(action));
}
return plan;
}
} // namespace XCEngine::UI::Editor::App