Files
XCEngine/editor/app/Windowing/Content/EditorWorkspaceWindowContentController.cpp

307 lines
11 KiB
C++

#include "Windowing/Content/EditorWorkspaceWindowContentController.h"
#include "Windowing/System/EditorWindowPresentationPolicy.h"
#include "Windowing/System/EditorWindowSystem.h"
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
#include <XCEditor/Workspace/UIEditorDetachedWindowPolicy.h>
#include <XCEditor/Workspace/UIEditorWorkspaceLayoutPersistence.h>
namespace XCEngine::UI::Editor::App {
namespace {
EditorWindowContentCursorKind ToContentCursorKind(ProjectPanel::CursorKind cursorKind) {
switch (cursorKind) {
case ProjectPanel::CursorKind::ResizeEW:
return EditorWindowContentCursorKind::ResizeEW;
case ProjectPanel::CursorKind::Arrow:
default:
return EditorWindowContentCursorKind::Arrow;
}
}
EditorWindowContentCursorKind ToContentCursorKind(
Widgets::UIEditorDockHostCursorKind cursorKind) {
switch (cursorKind) {
case Widgets::UIEditorDockHostCursorKind::ResizeEW:
return EditorWindowContentCursorKind::ResizeEW;
case Widgets::UIEditorDockHostCursorKind::ResizeNS:
return EditorWindowContentCursorKind::ResizeNS;
case Widgets::UIEditorDockHostCursorKind::Arrow:
default:
return EditorWindowContentCursorKind::Arrow;
}
}
EditorWorkspaceWindowProjection BuildWorkspaceProjectionFromController(
const UIEditorWorkspaceController& workspaceController,
std::string_view windowId) {
EditorWorkspaceWindowProjection projection = {};
projection.windowState.windowId = std::string(windowId);
projection.windowState.workspace = workspaceController.GetWorkspace();
projection.windowState.session = workspaceController.GetSession();
projection.minimumOuterSize = ResolveUIEditorDetachedWorkspaceMinimumOuterSize(
workspaceController);
projection.useDetachedTitleBarTabStrip = HasUIEditorSingleVisibleRootTab(workspaceController);
projection.tabStripTitleText = ResolveUIEditorDetachedWorkspaceTitle(workspaceController);
projection.detachedWindowTitleText = ResolveUIEditorDetachedWorkspaceTitle(workspaceController);
return projection;
}
} // namespace
EditorWorkspaceWindowContentController::EditorWorkspaceWindowContentController(
std::string windowId,
UIEditorWorkspaceController workspaceController,
EditorWindowSystem& windowSystem)
: m_windowId(std::move(windowId)),
m_workspaceController(std::move(workspaceController)),
m_windowSystem(windowSystem) {
RefreshProjectionFromWorkspaceController();
}
EditorWorkspaceWindowContentController::~EditorWorkspaceWindowContentController() = default;
EditorWindowContentCapabilities
EditorWorkspaceWindowContentController::GetCapabilities() const {
return EditorWindowContentCapabilities{
.workspace = true,
.dockHost = true,
.inputFeedback = true,
.titleBar = true,
.viewportRendering = true,
.utilityPanel = false,
};
}
EditorWindowWorkspaceBinding* EditorWorkspaceWindowContentController::TryGetWorkspaceBinding() {
return this;
}
const EditorWindowWorkspaceBinding*
EditorWorkspaceWindowContentController::TryGetWorkspaceBinding() const {
return this;
}
EditorWindowDockHostBinding* EditorWorkspaceWindowContentController::TryGetDockHostBinding() {
return this;
}
const EditorWindowDockHostBinding*
EditorWorkspaceWindowContentController::TryGetDockHostBinding() const {
return this;
}
const EditorWindowInputFeedbackBinding*
EditorWorkspaceWindowContentController::TryGetInputFeedbackBinding() const {
return this;
}
const EditorWindowTitleBarBinding*
EditorWorkspaceWindowContentController::TryGetTitleBarBinding() const {
return this;
}
const UIEditorWorkspaceController*
EditorWorkspaceWindowContentController::TryGetWorkspaceController() const {
return &m_workspaceController;
}
const EditorWorkspaceWindowProjection*
EditorWorkspaceWindowContentController::TryGetWorkspaceProjection() const {
return &m_projection;
}
void EditorWorkspaceWindowContentController::RefreshWorkspaceProjection(
EditorWorkspaceWindowProjection projection) {
projection.windowState.windowId = m_windowId;
const auto currentSnapshot = BuildUIEditorWorkspaceLayoutSnapshot(
m_workspaceController.GetWorkspace(),
m_workspaceController.GetSession());
const auto nextSnapshot = BuildUIEditorWorkspaceLayoutSnapshot(
projection.windowState.workspace,
projection.windowState.session);
if (!AreUIEditorWorkspaceLayoutSnapshotsEquivalent(currentSnapshot, nextSnapshot)) {
m_workspaceController = UIEditorWorkspaceController(
m_workspaceController.GetPanelRegistry(),
projection.windowState.workspace,
projection.windowState.session);
}
m_projection = std::move(projection);
}
void EditorWorkspaceWindowContentController::RefreshProjectionFromWorkspaceController(bool primary) {
const std::wstring preservedWindowTitle = m_projection.windowTitle;
m_projection = BuildWorkspaceProjectionFromController(m_workspaceController, m_windowId);
if (!primary) {
m_projection.windowTitle = ResolveEditorWindowPresentationTitle(
std::wstring_view{},
m_workspaceController.GetPanelRegistry(),
m_projection.windowState,
false);
} else if (!preservedWindowTitle.empty()) {
m_projection.windowTitle = preservedWindowTitle;
}
}
void EditorWorkspaceWindowContentController::RestoreWorkspaceControllerFromProjection() {
m_workspaceController = UIEditorWorkspaceController(
m_workspaceController.GetPanelRegistry(),
m_projection.windowState.workspace,
m_projection.windowState.session);
}
void EditorWorkspaceWindowContentController::Initialize(
const EditorWindowContentInitializationContext& context) {
m_shellRuntime.Initialize(context.repoRoot, context.textureHost, context.textMeasurer);
m_shellRuntime.AttachViewportWindowRenderer(context.viewportRenderer);
}
void EditorWorkspaceWindowContentController::Shutdown() {
m_shellRuntime.Shutdown();
}
void EditorWorkspaceWindowContentController::ResetInteractionState() {
m_shellRuntime.ResetInteractionState();
}
void EditorWorkspaceWindowContentController::SetViewportSurfacePresentationEnabled(bool enabled) {
m_shellRuntime.SetViewportSurfacePresentationEnabled(enabled);
}
EditorWindowFrameTransferRequests EditorWorkspaceWindowContentController::UpdateAndAppend(
const EditorWindowContentFrameContext& context,
::XCEngine::UI::UIDrawData& drawData) {
const auto beforeSnapshot = BuildUIEditorWorkspaceLayoutSnapshot(
m_workspaceController.GetWorkspace(),
m_workspaceController.GetSession());
EditorWindowFrameTransferRequests transferRequests = m_frameOrchestrator.UpdateAndAppend(
context.editorContext,
m_workspaceController,
m_shellRuntime,
context.bounds,
context.inputEvents,
context.cursorScreenPoint,
context.captureStatusText,
context.primary,
context.globalTabDragActive,
context.useDetachedTitleBarTabStrip,
drawData);
const auto afterSnapshot = BuildUIEditorWorkspaceLayoutSnapshot(
m_workspaceController.GetWorkspace(),
m_workspaceController.GetSession());
if (!AreUIEditorWorkspaceLayoutSnapshotsEquivalent(beforeSnapshot, afterSnapshot)) {
std::string error = {};
if (!m_windowSystem.CommitLiveWindowMutation(
m_windowId,
m_workspaceController,
error)) {
AppendUIEditorRuntimeTrace(
"window",
"workspace direct commit rejected for window '" +
m_windowId + "': " + error);
RestoreWorkspaceControllerFromProjection();
} else {
RefreshProjectionFromWorkspaceController(context.primary);
}
}
return transferRequests;
}
void EditorWorkspaceWindowContentController::RenderRequestedViewports(
const ::XCEngine::Rendering::RenderContext& renderContext) {
m_shellRuntime.RenderRequestedViewports(renderContext);
}
const UIEditorShellInteractionFrame&
EditorWorkspaceWindowContentController::GetShellFrame() const {
return m_shellRuntime.GetShellFrame();
}
const UIEditorShellInteractionState&
EditorWorkspaceWindowContentController::GetShellInteractionState() const {
return m_shellRuntime.GetShellInteractionState();
}
void EditorWorkspaceWindowContentController::SetExternalDockHostDropPreview(
const Widgets::UIEditorDockHostDropPreviewState& preview) {
m_shellRuntime.SetExternalDockHostDropPreview(preview);
}
void EditorWorkspaceWindowContentController::ClearExternalDockHostDropPreview() {
m_shellRuntime.ClearExternalDockHostDropPreview();
}
bool EditorWorkspaceWindowContentController::TryResolveDockTabDragHotspot(
std::string_view nodeId,
std::string_view panelId,
const ::XCEngine::UI::UIPoint& point,
::XCEngine::UI::UIPoint& outHotspot) const {
return m_shellRuntime.TryResolveDockTabDragHotspot(
nodeId,
panelId,
point,
outHotspot);
}
UIEditorDockHostTabDropTarget EditorWorkspaceWindowContentController::ResolveDockTabDropTarget(
const ::XCEngine::UI::UIPoint& point) const {
return m_shellRuntime.ResolveDockTabDropTarget(point);
}
bool EditorWorkspaceWindowContentController::HasHostedContentCapture() const {
return m_shellRuntime.HasHostedContentCapture();
}
bool EditorWorkspaceWindowContentController::HasShellInteractiveCapture() const {
return m_shellRuntime.HasShellInteractiveCapture();
}
bool EditorWorkspaceWindowContentController::HasInteractiveCapture() const {
return m_shellRuntime.HasInteractiveCapture();
}
EditorWindowContentCursorKind
EditorWorkspaceWindowContentController::GetHostedContentCursorKind() const {
return ToContentCursorKind(m_shellRuntime.GetHostedContentCursorKind());
}
EditorWindowContentCursorKind EditorWorkspaceWindowContentController::GetDockCursorKind() const {
return ToContentCursorKind(m_shellRuntime.GetDockCursorKind());
}
::XCEngine::UI::UISize EditorWorkspaceWindowContentController::ResolveMinimumOuterSize() const {
return m_projection.minimumOuterSize;
}
bool EditorWorkspaceWindowContentController::ShouldUseDetachedTitleBarTabStrip() const {
return m_projection.useDetachedTitleBarTabStrip;
}
std::string EditorWorkspaceWindowContentController::ResolveTabStripTitleText(
std::string_view fallbackTitle) const {
return m_projection.tabStripTitleText.empty()
? std::string(fallbackTitle)
: m_projection.tabStripTitleText;
}
std::string EditorWorkspaceWindowContentController::ResolveDetachedWindowTitleText(
std::string_view fallbackWindowTitle) const {
return m_projection.detachedWindowTitleText.empty()
? std::string(fallbackWindowTitle)
: m_projection.detachedWindowTitleText;
}
std::unique_ptr<EditorWindowContentController> CreateEditorWorkspaceWindowContentController(
std::string_view windowId,
UIEditorWorkspaceController workspaceController,
EditorWindowSystem& windowSystem) {
return std::make_unique<EditorWorkspaceWindowContentController>(
std::string(windowId),
std::move(workspaceController),
windowSystem);
}
} // namespace XCEngine::UI::Editor::App