checkpoint: commit current workspace state
This commit is contained in:
@@ -0,0 +1,311 @@
|
||||
#include "Windowing/Content/EditorWindowFrameOrchestrator.h"
|
||||
|
||||
#include "Composition/EditorContext.h"
|
||||
#include "Composition/EditorShellRuntime.h"
|
||||
#include "Composition/EditorShellVariant.h"
|
||||
#include "Support/EnvironmentFlags.h"
|
||||
#include "Windowing/Content/EditorWindowContentStyle.h"
|
||||
#include "Windowing/Utility/EditorUtilityWindowRequestSink.h"
|
||||
#include "Windowing/Workspace/WindowWorkspaceTransferQueue.h"
|
||||
|
||||
#include "Windowing/Workspace/UIEditorDetachedWindowPolicy.h"
|
||||
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
|
||||
#include <XCEditor/Workspace/UIEditorWorkspaceController.h>
|
||||
#include <XCEngine/UI/DrawData.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
namespace XCEngine::UI::Editor::App {
|
||||
|
||||
using namespace EditorWindowContentStyle;
|
||||
using ::XCEngine::UI::UIDrawData;
|
||||
using ::XCEngine::UI::UIDrawList;
|
||||
using ::XCEngine::UI::UIInputEvent;
|
||||
using ::XCEngine::UI::UIInputEventType;
|
||||
using ::XCEngine::UI::UIPoint;
|
||||
namespace WindowingDomain = ::XCEngine::UI::Editor::Windowing::Domain;
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsVerboseRuntimeTraceEnabled() {
|
||||
static const bool s_enabled = IsEnvironmentFlagEnabled("XCUIEDITOR_VERBOSE_TRACE");
|
||||
return s_enabled;
|
||||
}
|
||||
|
||||
std::string DescribeInputEventType(const UIInputEvent& event) {
|
||||
switch (event.type) {
|
||||
case UIInputEventType::PointerMove: return "PointerMove";
|
||||
case UIInputEventType::PointerEnter: return "PointerEnter";
|
||||
case UIInputEventType::PointerLeave: return "PointerLeave";
|
||||
case UIInputEventType::PointerButtonDown: return "PointerDown";
|
||||
case UIInputEventType::PointerButtonUp: return "PointerUp";
|
||||
case UIInputEventType::PointerWheel: return "PointerWheel";
|
||||
case UIInputEventType::KeyDown: return "KeyDown";
|
||||
case UIInputEventType::KeyUp: return "KeyUp";
|
||||
case UIInputEventType::Character: return "Character";
|
||||
case UIInputEventType::FocusGained: return "FocusGained";
|
||||
case UIInputEventType::FocusLost: return "FocusLost";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
WindowingDomain::WindowCursorType ToWindowCursorType(ProjectPanel::CursorKind cursorType) {
|
||||
switch (cursorType) {
|
||||
case ProjectPanel::CursorKind::ResizeEW:
|
||||
return WindowingDomain::WindowCursorType::ResizeEW;
|
||||
case ProjectPanel::CursorKind::Arrow:
|
||||
default:
|
||||
return WindowingDomain::WindowCursorType::Arrow;
|
||||
}
|
||||
}
|
||||
|
||||
WindowingDomain::WindowCursorType ToWindowCursorType(
|
||||
Widgets::UIEditorDockHostCursorKind cursorType) {
|
||||
switch (cursorType) {
|
||||
case Widgets::UIEditorDockHostCursorKind::ResizeEW:
|
||||
return WindowingDomain::WindowCursorType::ResizeEW;
|
||||
case Widgets::UIEditorDockHostCursorKind::ResizeNS:
|
||||
return WindowingDomain::WindowCursorType::ResizeNS;
|
||||
case Widgets::UIEditorDockHostCursorKind::Arrow:
|
||||
default:
|
||||
return WindowingDomain::WindowCursorType::Arrow;
|
||||
}
|
||||
}
|
||||
|
||||
WindowingDomain::WindowCaptureDemand BuildCaptureDemand(
|
||||
const EditorShellRuntime& shellRuntime) {
|
||||
return WindowingDomain::WindowCaptureDemand{
|
||||
.shellInteractive = shellRuntime.HasShellInteractiveCapture(),
|
||||
.hostedContent = shellRuntime.HasHostedContentCapture(),
|
||||
};
|
||||
}
|
||||
|
||||
WindowingDomain::WindowCursorType ResolveContentCursorType(
|
||||
const EditorShellRuntime& shellRuntime) {
|
||||
const WindowingDomain::WindowCursorType hostedCursorType =
|
||||
ToWindowCursorType(shellRuntime.GetHostedContentCursorType());
|
||||
if (hostedCursorType != WindowingDomain::WindowCursorType::Arrow) {
|
||||
return hostedCursorType;
|
||||
}
|
||||
|
||||
return ToWindowCursorType(shellRuntime.GetDockCursorType());
|
||||
}
|
||||
|
||||
void QueueWorkspaceTransferRequest(
|
||||
WindowWorkspaceTransferQueue& workspaceTransferQueue,
|
||||
WindowWorkspaceTransferRequest::Type type,
|
||||
std::string_view sourceWindowId,
|
||||
std::string sourceNodeId,
|
||||
std::string panelId,
|
||||
std::int32_t cursorScreenX,
|
||||
std::int32_t cursorScreenY) {
|
||||
WindowWorkspaceTransferRequest request = {};
|
||||
request.type = type;
|
||||
request.sourceWindowId = std::string(sourceWindowId);
|
||||
request.sourceNodeId = std::move(sourceNodeId);
|
||||
request.panelId = std::move(panelId);
|
||||
request.screenX = cursorScreenX;
|
||||
request.screenY = cursorScreenY;
|
||||
request.hasScreenPoint = true;
|
||||
workspaceTransferQueue.QueueWorkspaceTransferRequest(request);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EditorWindowContentUpdateResult EditorWindowFrameOrchestrator::UpdateAndAppend(
|
||||
EditorContext& editorContext,
|
||||
std::string_view sourceWindowId,
|
||||
EditorUtilityWindowResultState& utilityWindowResultState,
|
||||
EditorUtilityWindowRequestSink& utilityRequestSink,
|
||||
WindowWorkspaceTransferQueue& workspaceTransferQueue,
|
||||
UIEditorWorkspaceController& workspaceController,
|
||||
EditorShellRuntime& shellRuntime,
|
||||
const ::XCEngine::UI::UIRect& workspaceBounds,
|
||||
const std::vector<UIInputEvent>& frameEvents,
|
||||
std::string_view captureStatusText,
|
||||
bool primary,
|
||||
bool globalTabDragActive,
|
||||
bool useDetachedTitleBarTabStrip,
|
||||
std::int32_t cursorScreenX,
|
||||
std::int32_t cursorScreenY,
|
||||
bool hasCursorScreenPoint,
|
||||
UIDrawData& drawData) const {
|
||||
LogInputTrace(
|
||||
editorContext,
|
||||
workspaceController,
|
||||
shellRuntime.GetShellInteractionState(),
|
||||
frameEvents);
|
||||
|
||||
utilityRequestSink.ConfigureFrameSource(
|
||||
sourceWindowId,
|
||||
cursorScreenX,
|
||||
cursorScreenY,
|
||||
hasCursorScreenPoint);
|
||||
shellRuntime.Update(
|
||||
editorContext,
|
||||
utilityWindowResultState,
|
||||
utilityRequestSink,
|
||||
workspaceController,
|
||||
workspaceBounds,
|
||||
frameEvents,
|
||||
captureStatusText,
|
||||
primary ? EditorShellVariant::Primary : EditorShellVariant::DetachedWindow,
|
||||
useDetachedTitleBarTabStrip,
|
||||
useDetachedTitleBarTabStrip ? kBorderlessTitleBarHeightDips : 0.0f,
|
||||
primary ? 0.0f : kBorderlessTitleBarHeightDips);
|
||||
const UIEditorShellInteractionFrame& shellFrame = shellRuntime.GetShellFrame();
|
||||
const UIEditorDockHostInteractionState& dockHostInteractionState =
|
||||
shellRuntime.GetShellInteractionState().workspaceInteractionState.dockHostInteractionState;
|
||||
|
||||
LogFrameInteractionTrace(workspaceController, frameEvents, shellFrame);
|
||||
EditorWindowContentUpdateResult updateResult = {};
|
||||
updateResult.contentOutput.captureDemand = BuildCaptureDemand(shellRuntime);
|
||||
updateResult.contentOutput.cursorType = ResolveContentCursorType(shellRuntime);
|
||||
updateResult.contentOutput.titleBarMode =
|
||||
HasUIEditorSingleVisibleRootTab(workspaceController)
|
||||
? WindowingDomain::WindowTitleBarMode::DetachedTabStrip
|
||||
: WindowingDomain::WindowTitleBarMode::SystemChrome;
|
||||
AppendWorkspaceTransferRequests(
|
||||
sourceWindowId,
|
||||
globalTabDragActive,
|
||||
dockHostInteractionState,
|
||||
shellFrame,
|
||||
cursorScreenX,
|
||||
cursorScreenY,
|
||||
hasCursorScreenPoint,
|
||||
workspaceTransferQueue);
|
||||
for (const WorkspaceTraceEntry& entry : shellRuntime.GetTraceEntries()) {
|
||||
AppendUIEditorRuntimeTrace(entry.channel, entry.message);
|
||||
}
|
||||
|
||||
shellRuntime.Append(drawData);
|
||||
return updateResult;
|
||||
}
|
||||
|
||||
void EditorWindowFrameOrchestrator::AppendInvalidFrame(
|
||||
EditorContext& editorContext,
|
||||
UIDrawList& drawList) const {
|
||||
drawList.AddText(
|
||||
UIPoint(28.0f, 28.0f),
|
||||
"Editor shell asset invalid.",
|
||||
kShellTextColor,
|
||||
16.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(28.0f, 54.0f),
|
||||
editorContext.GetValidationMessage().empty()
|
||||
? std::string("Unknown validation error.")
|
||||
: editorContext.GetValidationMessage(),
|
||||
kShellMutedTextColor,
|
||||
12.0f);
|
||||
}
|
||||
|
||||
std::string EditorWindowFrameOrchestrator::DescribeInputEvents(
|
||||
const std::vector<UIInputEvent>& events) const {
|
||||
std::ostringstream stream = {};
|
||||
stream << "events=[";
|
||||
for (std::size_t index = 0; index < events.size(); ++index) {
|
||||
if (index > 0u) {
|
||||
stream << " | ";
|
||||
}
|
||||
|
||||
const UIInputEvent& event = events[index];
|
||||
stream << DescribeInputEventType(event)
|
||||
<< '@'
|
||||
<< static_cast<int>(event.position.x)
|
||||
<< ','
|
||||
<< static_cast<int>(event.position.y);
|
||||
}
|
||||
stream << ']';
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
void EditorWindowFrameOrchestrator::LogInputTrace(
|
||||
EditorContext& editorContext,
|
||||
const UIEditorWorkspaceController& workspaceController,
|
||||
const UIEditorShellInteractionState& shellInteractionState,
|
||||
const std::vector<UIInputEvent>& frameEvents) const {
|
||||
if (frameEvents.empty() || !IsVerboseRuntimeTraceEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AppendUIEditorRuntimeTrace(
|
||||
"input",
|
||||
DescribeInputEvents(frameEvents) + " | " +
|
||||
editorContext.DescribeWorkspaceState(
|
||||
workspaceController,
|
||||
shellInteractionState));
|
||||
}
|
||||
|
||||
void EditorWindowFrameOrchestrator::LogFrameInteractionTrace(
|
||||
const UIEditorWorkspaceController& workspaceController,
|
||||
const std::vector<UIInputEvent>& frameEvents,
|
||||
const UIEditorShellInteractionFrame& shellFrame) const {
|
||||
if (!IsVerboseRuntimeTraceEnabled() ||
|
||||
(frameEvents.empty() &&
|
||||
!shellFrame.result.workspaceResult.dockHostResult.layoutChanged &&
|
||||
!shellFrame.result.workspaceResult.dockHostResult.commandExecuted)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostringstream frameTrace = {};
|
||||
frameTrace << "result consumed="
|
||||
<< (shellFrame.result.consumed ? "true" : "false")
|
||||
<< " layoutChanged="
|
||||
<< (shellFrame.result.workspaceResult.dockHostResult.layoutChanged ? "true"
|
||||
: "false")
|
||||
<< " commandExecuted="
|
||||
<< (shellFrame.result.workspaceResult.dockHostResult.commandExecuted ? "true"
|
||||
: "false")
|
||||
<< " active="
|
||||
<< workspaceController.GetWorkspace().activePanelId
|
||||
<< " message="
|
||||
<< shellFrame.result.workspaceResult.dockHostResult.layoutResult.message;
|
||||
AppendUIEditorRuntimeTrace("frame", frameTrace.str());
|
||||
}
|
||||
|
||||
void EditorWindowFrameOrchestrator::AppendWorkspaceTransferRequests(
|
||||
std::string_view sourceWindowId,
|
||||
bool globalTabDragActive,
|
||||
const UIEditorDockHostInteractionState& dockHostInteractionState,
|
||||
const UIEditorShellInteractionFrame& shellFrame,
|
||||
std::int32_t cursorScreenX,
|
||||
std::int32_t cursorScreenY,
|
||||
bool hasCursorScreenPoint,
|
||||
WindowWorkspaceTransferQueue& workspaceTransferQueue) const {
|
||||
if (!globalTabDragActive &&
|
||||
!dockHostInteractionState.activeTabDragNodeId.empty() &&
|
||||
!dockHostInteractionState.activeTabDragPanelId.empty() &&
|
||||
hasCursorScreenPoint) {
|
||||
QueueWorkspaceTransferRequest(
|
||||
workspaceTransferQueue,
|
||||
WindowWorkspaceTransferRequest::Type::StartGlobalTabDrag,
|
||||
sourceWindowId,
|
||||
dockHostInteractionState.activeTabDragNodeId,
|
||||
dockHostInteractionState.activeTabDragPanelId,
|
||||
cursorScreenX,
|
||||
cursorScreenY);
|
||||
}
|
||||
|
||||
if (shellFrame.result.workspaceResult.dockHostResult.detachRequested &&
|
||||
hasCursorScreenPoint) {
|
||||
QueueWorkspaceTransferRequest(
|
||||
workspaceTransferQueue,
|
||||
WindowWorkspaceTransferRequest::Type::DetachPanel,
|
||||
sourceWindowId,
|
||||
shellFrame.result.workspaceResult.dockHostResult.detachedNodeId,
|
||||
shellFrame.result.workspaceResult.dockHostResult.detachedPanelId,
|
||||
cursorScreenX,
|
||||
cursorScreenY);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user