Refactor editor window synchronization flow
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user