144 lines
5.0 KiB
C++
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
|