Files
XCEngine/editor/app/Windowing/Frame/EditorWindowFrameOrchestrator.cpp

221 lines
8.2 KiB
C++

#include "Windowing/Frame/EditorWindowFrameOrchestrator.h"
#include "Composition/EditorContext.h"
#include "Composition/EditorShellRuntime.h"
#include "Composition/EditorShellVariant.h"
#include "Windowing/EditorWindowShared.h"
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
#include <XCEditor/Workspace/UIEditorWorkspaceController.h>
#include <XCEngine/UI/DrawData.h>
#include <sstream>
namespace XCEngine::UI::Editor::App {
using ::XCEngine::UI::UIDrawData;
using ::XCEngine::UI::UIDrawList;
using ::XCEngine::UI::UIInputEvent;
using ::XCEngine::UI::UIInputEventType;
using ::XCEngine::UI::UIPoint;
namespace {
bool IsVerboseRuntimeTraceEnabled() {
static const bool s_enabled = IsEditorWindowVerboseRuntimeTraceEnabled();
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";
}
}
} // namespace
EditorWindowFrameTransferRequests EditorWindowFrameOrchestrator::UpdateAndAppend(
EditorContext& editorContext,
UIEditorWorkspaceController& workspaceController,
EditorShellRuntime& shellRuntime,
const ::XCEngine::UI::UIRect& workspaceBounds,
const std::vector<UIInputEvent>& frameEvents,
const std::optional<EditorWindowScreenPoint>& cursorScreenPoint,
std::string_view captureStatusText,
bool primary,
bool globalTabDragActive,
bool useDetachedTitleBarTabStrip,
UIDrawData& drawData) const {
LogInputTrace(
editorContext,
workspaceController,
shellRuntime.GetShellInteractionState(),
frameEvents);
shellRuntime.Update(
editorContext,
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);
EditorWindowFrameTransferRequests transferRequests =
BuildShellTransferRequests(
globalTabDragActive,
cursorScreenPoint,
dockHostInteractionState,
shellFrame);
if (const std::optional<EditorUtilityWindowKind> requestedKind =
editorContext.ConsumeOpenUtilityWindowRequest();
requestedKind.has_value()) {
transferRequests.utility.openUtilityWindow = EditorWindowOpenUtilityWindowRequest{
.kind = *requestedKind,
.useCursorPlacement = cursorScreenPoint.has_value(),
};
if (transferRequests.utility.openUtilityWindow->useCursorPlacement) {
transferRequests.utility.openUtilityWindow->screenPoint = *cursorScreenPoint;
}
}
for (const WorkspaceTraceEntry& entry : shellRuntime.GetTraceEntries()) {
AppendUIEditorRuntimeTrace(entry.channel, entry.message);
}
shellRuntime.Append(drawData);
return transferRequests;
}
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());
}
EditorWindowFrameTransferRequests EditorWindowFrameOrchestrator::BuildShellTransferRequests(
bool globalTabDragActive,
const std::optional<EditorWindowScreenPoint>& cursorScreenPoint,
const UIEditorDockHostInteractionState& dockHostInteractionState,
const UIEditorShellInteractionFrame& shellFrame) const {
EditorWindowFrameTransferRequests transferRequests = {};
if (!cursorScreenPoint.has_value()) {
return transferRequests;
}
if (!globalTabDragActive &&
!dockHostInteractionState.activeTabDragNodeId.empty() &&
!dockHostInteractionState.activeTabDragPanelId.empty()) {
transferRequests.workspace.beginGlobalTabDrag = EditorWindowPanelTransferRequest{
dockHostInteractionState.activeTabDragNodeId,
dockHostInteractionState.activeTabDragPanelId,
*cursorScreenPoint,
};
}
if (shellFrame.result.workspaceResult.dockHostResult.detachRequested) {
transferRequests.workspace.detachPanel = EditorWindowPanelTransferRequest{
shellFrame.result.workspaceResult.dockHostResult.detachedNodeId,
shellFrame.result.workspaceResult.dockHostResult.detachedPanelId,
*cursorScreenPoint,
};
}
return transferRequests;
}
} // namespace XCEngine::UI::Editor::App