221 lines
8.2 KiB
C++
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
|
|
|