关键节点

This commit is contained in:
2026-04-25 16:46:01 +08:00
parent 6002d86a7e
commit ef41c44464
516 changed files with 6175 additions and 12401 deletions

View File

@@ -0,0 +1,25 @@
#pragma once
#include <XCEditor/Panels/UIEditorPanelRegistry.h>
#include <XCEditor/Workspace/UIEditorWorkspaceController.h>
#include <string>
#include <string_view>
namespace XCEngine::UI::Editor {
const UIEditorPanelDescriptor* ResolveUIEditorSingleVisibleRootPanelDescriptor(
const UIEditorWorkspaceController& controller);
bool HasUIEditorSingleVisibleRootTab(
const UIEditorWorkspaceController& controller);
std::string ResolveUIEditorDetachedWorkspaceTitle(
const UIEditorWorkspaceController& controller,
std::string_view fallbackTitle = {});
::XCEngine::UI::UISize ResolveUIEditorDetachedWorkspaceMinimumOuterSize(
const UIEditorWorkspaceController& controller,
const ::XCEngine::UI::UISize& fallbackSize = ::XCEngine::UI::UISize(640.0f, 360.0f));
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,91 @@
#pragma once
#include <XCEditor/Workspace/UIEditorWindowWorkspaceModel.h>
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
namespace XCEngine::UI::Editor {
enum class UIEditorWindowWorkspaceOperationStatus : std::uint8_t {
Changed = 0,
NoOp,
Rejected
};
struct UIEditorWindowWorkspaceOperationResult {
UIEditorWindowWorkspaceOperationStatus status =
UIEditorWindowWorkspaceOperationStatus::Rejected;
std::string message = {};
std::string sourceWindowId = {};
std::string targetWindowId = {};
std::string panelId = {};
std::string activeWindowId = {};
std::vector<std::string> windowIds = {};
};
std::string_view GetUIEditorWindowWorkspaceOperationStatusName(
UIEditorWindowWorkspaceOperationStatus status);
class UIEditorWindowWorkspaceController {
public:
UIEditorWindowWorkspaceController() = default;
UIEditorWindowWorkspaceController(
UIEditorPanelRegistry panelRegistry,
UIEditorWindowWorkspaceSet windowSet);
const UIEditorPanelRegistry& GetPanelRegistry() const {
return m_panelRegistry;
}
const UIEditorWindowWorkspaceSet& GetWindowSet() const {
return m_windowSet;
}
UIEditorWindowWorkspaceValidationResult ValidateState() const;
UIEditorWindowWorkspaceOperationResult DetachPanelToNewWindow(
std::string_view sourceWindowId,
std::string_view sourceNodeId,
std::string_view panelId,
std::string_view preferredNewWindowId = {});
UIEditorWindowWorkspaceOperationResult MovePanelToStack(
std::string_view sourceWindowId,
std::string_view sourceNodeId,
std::string_view panelId,
std::string_view targetWindowId,
std::string_view targetNodeId,
std::size_t targetVisibleInsertionIndex);
UIEditorWindowWorkspaceOperationResult DockPanelRelative(
std::string_view sourceWindowId,
std::string_view sourceNodeId,
std::string_view panelId,
std::string_view targetWindowId,
std::string_view targetNodeId,
UIEditorWorkspaceDockPlacement placement,
float splitRatio = 0.5f);
private:
UIEditorWindowWorkspaceOperationResult BuildOperationResult(
UIEditorWindowWorkspaceOperationStatus status,
std::string message,
std::string_view sourceWindowId,
std::string_view targetWindowId,
std::string_view panelId) const;
std::string MakeUniqueWindowId(std::string_view base) const;
UIEditorPanelRegistry m_panelRegistry = {};
UIEditorWindowWorkspaceSet m_windowSet = {};
};
UIEditorWindowWorkspaceController BuildDefaultUIEditorWindowWorkspaceController(
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWorkspaceModel& workspace,
std::string primaryWindowId = "main-window");
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,63 @@
#pragma once
#include <XCEditor/Panels/UIEditorPanelRegistry.h>
#include <XCEditor/Workspace/UIEditorWorkspaceSession.h>
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
namespace XCEngine::UI::Editor {
struct UIEditorWindowWorkspaceState {
std::string windowId = {};
UIEditorWorkspaceModel workspace = {};
UIEditorWorkspaceSession session = {};
};
struct UIEditorWindowWorkspaceSet {
std::string primaryWindowId = {};
std::string activeWindowId = {};
std::vector<UIEditorWindowWorkspaceState> windows = {};
};
enum class UIEditorWindowWorkspaceValidationCode : std::uint8_t {
None = 0,
InvalidPanelRegistry,
EmptyWindowId,
DuplicateWindowId,
DuplicatePanelAcrossWindows,
MissingPrimaryWindow,
MissingActiveWindow,
InvalidWorkspace,
InvalidSession
};
struct UIEditorWindowWorkspaceValidationResult {
UIEditorWindowWorkspaceValidationCode code = UIEditorWindowWorkspaceValidationCode::None;
std::string message = {};
[[nodiscard]] bool IsValid() const {
return code == UIEditorWindowWorkspaceValidationCode::None;
}
};
UIEditorWindowWorkspaceSet BuildDefaultUIEditorWindowWorkspaceSet(
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWorkspaceModel& workspace,
std::string primaryWindowId = "main-window");
const UIEditorWindowWorkspaceState* FindUIEditorWindowWorkspaceState(
const UIEditorWindowWorkspaceSet& windowSet,
std::string_view windowId);
UIEditorWindowWorkspaceState* FindMutableUIEditorWindowWorkspaceState(
UIEditorWindowWorkspaceSet& windowSet,
std::string_view windowId);
UIEditorWindowWorkspaceValidationResult ValidateUIEditorWindowWorkspaceSet(
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWindowWorkspaceSet& windowSet);
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,145 @@
#pragma once
#include <XCEditor/Foundation/UIEditorTextMeasurement.h>
#include <XCEditor/Panels/UIEditorPanelContentHost.h>
#include <XCEditor/Panels/UIEditorPanelRegistry.h>
#include <XCEditor/Viewport/UIEditorViewportShell.h>
#include <XCEditor/Workspace/UIEditorWorkspaceInputOwner.h>
#include <XCEditor/Workspace/UIEditorWorkspaceSession.h>
#include <XCEditor/Docking/UIEditorDockHost.h>
#include <XCEngine/UI/DrawData.h>
#include <string>
#include <string_view>
#include <vector>
namespace XCEngine::UI::Editor {
struct UIEditorWorkspacePanelPresentationModel {
std::string panelId = {};
UIEditorPanelPresentationKind kind = UIEditorPanelPresentationKind::Placeholder;
UIEditorViewportShellModel viewportShellModel = {};
};
struct UIEditorWorkspacePanelPresentationState {
std::string panelId = {};
UIEditorViewportShellState viewportShellState = {};
};
struct UIEditorWorkspaceComposeState {
UIEditorPanelContentHostState contentHostState = {};
std::vector<UIEditorWorkspacePanelPresentationState> panelStates = {};
};
struct UIEditorWorkspaceViewportComposeRequest {
std::string panelId = {};
::XCEngine::UI::UIRect bounds = {};
UIEditorViewportShellModel viewportShellModel = {};
UIEditorViewportShellRequest viewportShellRequest = {};
};
struct UIEditorWorkspaceComposeRequest {
Widgets::UIEditorDockHostLayout dockHostLayout = {};
UIEditorPanelContentHostRequest contentHostRequest = {};
std::vector<UIEditorWorkspaceViewportComposeRequest> viewportRequests = {};
};
struct UIEditorWorkspaceViewportComposeFrame {
std::string panelId = {};
::XCEngine::UI::UIRect bounds = {};
UIEditorViewportShellModel viewportShellModel = {};
UIEditorViewportShellFrame viewportShellFrame = {};
};
struct UIEditorWorkspaceComposeFrame {
Widgets::UIEditorDockHostLayout dockHostLayout = {};
UIEditorPanelContentHostFrame contentHostFrame = {};
std::vector<UIEditorWorkspaceViewportComposeFrame> viewportFrames = {};
};
struct UIEditorWorkspaceComposeAppendOptions {
bool deferDockPreviewOverlay = false;
bool includeViewportTextures = true;
};
const UIEditorWorkspacePanelPresentationModel* FindUIEditorWorkspacePanelPresentationModel(
const std::vector<UIEditorWorkspacePanelPresentationModel>& presentations,
std::string_view panelId);
const UIEditorWorkspacePanelPresentationState* FindUIEditorWorkspacePanelPresentationState(
const UIEditorWorkspaceComposeState& state,
std::string_view panelId);
const UIEditorWorkspaceViewportComposeRequest* FindUIEditorWorkspaceViewportPresentationRequest(
const UIEditorWorkspaceComposeRequest& request,
std::string_view panelId);
const UIEditorWorkspaceViewportComposeFrame* FindUIEditorWorkspaceViewportPresentationFrame(
const UIEditorWorkspaceComposeFrame& frame,
std::string_view panelId);
UIEditorWorkspaceComposeRequest ResolveUIEditorWorkspaceComposeRequest(
const Widgets::UIEditorDockHostLayout& dockHostLayout,
const UIEditorPanelRegistry& panelRegistry,
const std::vector<UIEditorWorkspacePanelPresentationModel>& presentations,
const Widgets::UIEditorViewportSlotMetrics& viewportMetrics = {},
const UIEditorTextMeasurer* textMeasurer = nullptr);
UIEditorWorkspaceComposeRequest ResolveUIEditorWorkspaceComposeRequest(
const ::XCEngine::UI::UIRect& bounds,
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session,
const std::vector<UIEditorWorkspacePanelPresentationModel>& presentations,
const Widgets::UIEditorDockHostState& dockHostState = {},
const Widgets::UIEditorDockHostMetrics& dockHostMetrics = {},
const Widgets::UIEditorViewportSlotMetrics& viewportMetrics = {},
const UIEditorTextMeasurer* textMeasurer = nullptr);
UIEditorWorkspaceComposeFrame UpdateUIEditorWorkspaceCompose(
UIEditorWorkspaceComposeState& state,
const UIEditorWorkspaceComposeRequest& request,
const UIEditorPanelRegistry& panelRegistry,
const std::vector<UIEditorWorkspacePanelPresentationModel>& presentations,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
const UIEditorWorkspaceInputOwner* inputOwner = nullptr);
UIEditorWorkspaceComposeFrame UpdateUIEditorWorkspaceCompose(
UIEditorWorkspaceComposeState& state,
const ::XCEngine::UI::UIRect& bounds,
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session,
const std::vector<UIEditorWorkspacePanelPresentationModel>& presentations,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
const Widgets::UIEditorDockHostState& dockHostState = {},
const Widgets::UIEditorDockHostMetrics& dockHostMetrics = {},
const Widgets::UIEditorViewportSlotMetrics& viewportMetrics = {},
const UIEditorWorkspaceInputOwner* inputOwner = nullptr,
const UIEditorTextMeasurer* textMeasurer = nullptr);
std::vector<std::string> CollectUIEditorWorkspaceComposeExternalBodyPanelIds(
const UIEditorWorkspaceComposeFrame& frame);
void AppendUIEditorWorkspaceCompose(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorWorkspaceComposeFrame& frame,
const Widgets::UIEditorDockHostPalette& dockHostPalette = {},
const Widgets::UIEditorDockHostMetrics& dockHostMetrics = {},
const Widgets::UIEditorViewportSlotPalette& viewportPalette = {},
const Widgets::UIEditorViewportSlotMetrics& viewportMetrics = {},
const UIEditorWorkspaceComposeAppendOptions& options = {});
void AppendUIEditorWorkspaceComposeOverlay(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorWorkspaceComposeFrame& frame,
const Widgets::UIEditorDockHostPalette& dockHostPalette = {},
const Widgets::UIEditorDockHostMetrics& dockHostMetrics = {});
void AppendUIEditorWorkspaceComposeViewportTextures(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorWorkspaceComposeFrame& frame,
const Widgets::UIEditorViewportSlotPalette& viewportPalette = {});
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,152 @@
#pragma once
#include <XCEditor/Workspace/UIEditorWorkspaceLayoutPersistence.h>
#include <XCEditor/Workspace/UIEditorWorkspaceSession.h>
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
namespace XCEngine::UI::Editor {
enum class UIEditorWorkspaceCommandKind : std::uint8_t {
OpenPanel = 0,
ClosePanel,
ShowPanel,
HidePanel,
ActivatePanel,
ResetWorkspace
};
enum class UIEditorWorkspaceCommandStatus : std::uint8_t {
Changed = 0,
NoOp,
Rejected
};
struct UIEditorWorkspaceCommand {
UIEditorWorkspaceCommandKind kind = UIEditorWorkspaceCommandKind::ActivatePanel;
std::string panelId = {};
};
struct UIEditorWorkspaceCommandResult {
UIEditorWorkspaceCommandKind kind = UIEditorWorkspaceCommandKind::ActivatePanel;
UIEditorWorkspaceCommandStatus status = UIEditorWorkspaceCommandStatus::Rejected;
std::string panelId = {};
std::string message = {};
std::string activePanelId = {};
std::vector<std::string> visiblePanelIds = {};
};
enum class UIEditorWorkspaceControllerValidationCode : std::uint8_t {
None = 0,
InvalidPanelRegistry,
InvalidWorkspace,
InvalidWorkspaceSession
};
struct UIEditorWorkspaceControllerValidationResult {
UIEditorWorkspaceControllerValidationCode code =
UIEditorWorkspaceControllerValidationCode::None;
std::string message = {};
[[nodiscard]] bool IsValid() const {
return code == UIEditorWorkspaceControllerValidationCode::None;
}
};
std::string_view GetUIEditorWorkspaceCommandKindName(UIEditorWorkspaceCommandKind kind);
std::string_view GetUIEditorWorkspaceCommandStatusName(UIEditorWorkspaceCommandStatus status);
enum class UIEditorWorkspaceLayoutOperationStatus : std::uint8_t {
Changed = 0,
NoOp,
Rejected
};
struct UIEditorWorkspaceLayoutOperationResult {
UIEditorWorkspaceLayoutOperationStatus status =
UIEditorWorkspaceLayoutOperationStatus::Rejected;
std::string message = {};
std::string activePanelId = {};
std::vector<std::string> visiblePanelIds = {};
};
std::string_view GetUIEditorWorkspaceLayoutOperationStatusName(
UIEditorWorkspaceLayoutOperationStatus status);
class UIEditorWorkspaceController {
public:
UIEditorWorkspaceController() = default;
UIEditorWorkspaceController(
UIEditorPanelRegistry panelRegistry,
UIEditorWorkspaceModel workspace,
UIEditorWorkspaceSession session);
const UIEditorPanelRegistry& GetPanelRegistry() const {
return m_panelRegistry;
}
const UIEditorWorkspaceModel& GetWorkspace() const {
return m_workspace;
}
const UIEditorWorkspaceSession& GetSession() const {
return m_session;
}
UIEditorWorkspaceControllerValidationResult ValidateState() const;
UIEditorWorkspaceLayoutSnapshot CaptureLayoutSnapshot() const;
UIEditorWorkspaceLayoutOperationResult RestoreLayoutSnapshot(
const UIEditorWorkspaceLayoutSnapshot& snapshot);
UIEditorWorkspaceLayoutOperationResult RestoreSerializedLayout(
std::string_view serializedLayout);
UIEditorWorkspaceLayoutOperationResult SetSplitRatio(
std::string_view nodeId,
float splitRatio);
UIEditorWorkspaceLayoutOperationResult MoveTabToStack(
std::string_view sourceNodeId,
std::string_view panelId,
std::string_view targetNodeId,
std::size_t targetVisibleInsertionIndex);
UIEditorWorkspaceLayoutOperationResult DockTabRelative(
std::string_view sourceNodeId,
std::string_view panelId,
std::string_view targetNodeId,
UIEditorWorkspaceDockPlacement placement,
float splitRatio = 0.5f);
UIEditorWorkspaceCommandResult Dispatch(const UIEditorWorkspaceCommand& command);
private:
UIEditorWorkspaceCommandResult BuildResult(
const UIEditorWorkspaceCommand& command,
UIEditorWorkspaceCommandStatus status,
std::string message) const;
UIEditorWorkspaceCommandResult FinalizeMutation(
const UIEditorWorkspaceCommand& command,
bool changed,
std::string changedMessage,
std::string unexpectedFailureMessage,
const UIEditorWorkspaceModel& previousWorkspace,
const UIEditorWorkspaceSession& previousSession);
UIEditorWorkspaceLayoutOperationResult BuildLayoutOperationResult(
UIEditorWorkspaceLayoutOperationStatus status,
std::string message) const;
const UIEditorPanelDescriptor* FindPanelDescriptor(std::string_view panelId) const;
UIEditorPanelRegistry m_panelRegistry = {};
UIEditorWorkspaceModel m_baselineWorkspace = {};
UIEditorWorkspaceSession m_baselineSession = {};
UIEditorWorkspaceModel m_workspace = {};
UIEditorWorkspaceSession m_session = {};
};
UIEditorWorkspaceController BuildDefaultUIEditorWorkspaceController(
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWorkspaceModel& workspace);
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,54 @@
#pragma once
#include <XCEditor/Panels/UIEditorPanelContentHost.h>
#include <XCEditor/Docking/UIEditorDockHost.h>
#include <XCEngine/UI/Types.h>
#include <cstdint>
#include <string>
#include <string_view>
namespace XCEngine::UI::Editor {
enum class UIEditorWorkspaceInputOwnerKind : std::uint8_t {
None = 0,
DockHost,
HostedPanel,
Viewport
};
struct UIEditorWorkspaceInputOwner {
UIEditorWorkspaceInputOwnerKind kind = UIEditorWorkspaceInputOwnerKind::None;
std::string panelId = {};
};
std::string_view GetUIEditorWorkspaceInputOwnerKindName(
UIEditorWorkspaceInputOwnerKind kind);
bool AreUIEditorWorkspaceInputOwnersEquivalent(
const UIEditorWorkspaceInputOwner& lhs,
const UIEditorWorkspaceInputOwner& rhs);
bool IsUIEditorWorkspaceDockHostInputOwner(
const UIEditorWorkspaceInputOwner& owner);
bool IsUIEditorWorkspaceHostedPanelInputOwner(
const UIEditorWorkspaceInputOwner& owner,
std::string_view panelId = {});
bool IsUIEditorWorkspaceViewportInputOwner(
const UIEditorWorkspaceInputOwner& owner,
std::string_view panelId = {});
UIEditorWorkspaceInputOwner ResolveUIEditorWorkspacePointerInputOwner(
const Widgets::UIEditorDockHostLayout& dockHostLayout,
const UIEditorPanelContentHostFrame& contentHostFrame,
const ::XCEngine::UI::UIPoint& pointerPosition);
UIEditorWorkspaceInputOwner NormalizeUIEditorWorkspaceInputOwner(
UIEditorWorkspaceInputOwner owner,
const Widgets::UIEditorDockHostLayout& dockHostLayout,
const UIEditorPanelContentHostFrame& contentHostFrame);
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,57 @@
#pragma once
#include <XCEditor/Foundation/UIEditorTextMeasurement.h>
#include <XCEditor/Docking/UIEditorDockHostInteraction.h>
#include <XCEditor/Panels/UIEditorPanelHostLifecycle.h>
#include <XCEditor/Workspace/UIEditorWorkspaceCompose.h>
#include <XCEditor/Workspace/UIEditorWorkspaceInputOwner.h>
#include <XCEngine/UI/Types.h>
#include <string>
#include <vector>
namespace XCEngine::UI::Editor {
struct UIEditorWorkspaceInteractionModel {
std::vector<UIEditorWorkspacePanelPresentationModel> workspacePresentations = {};
};
struct UIEditorWorkspaceInteractionState {
UIEditorDockHostInteractionState dockHostInteractionState = {};
UIEditorPanelHostLifecycleState panelHostLifecycleState = {};
UIEditorWorkspaceComposeState composeState = {};
UIEditorWorkspaceInputOwner inputOwner = {};
};
struct UIEditorWorkspaceInteractionResult {
bool consumed = false;
bool requestPointerCapture = false;
bool releasePointerCapture = false;
bool viewportInteractionChanged = false;
std::string viewportPanelId = {};
UIEditorViewportInputBridgeFrame viewportInputFrame = {};
UIEditorDockHostInteractionResult dockHostResult = {};
};
struct UIEditorWorkspaceInteractionFrame {
UIEditorDockHostInteractionFrame dockHostFrame = {};
UIEditorPanelHostLifecycleFrame panelHostLifecycleFrame = {};
UIEditorWorkspaceComposeFrame composeFrame = {};
UIEditorWorkspaceInteractionResult result = {};
UIEditorWorkspaceInputOwner previousInputOwner = {};
UIEditorWorkspaceInputOwner inputOwner = {};
bool inputOwnerChanged = false;
};
UIEditorWorkspaceInteractionFrame UpdateUIEditorWorkspaceInteraction(
UIEditorWorkspaceInteractionState& state,
UIEditorWorkspaceController& controller,
const ::XCEngine::UI::UIRect& bounds,
const UIEditorWorkspaceInteractionModel& model,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
const Widgets::UIEditorDockHostMetrics& dockHostMetrics = {},
const Widgets::UIEditorViewportSlotMetrics& viewportMetrics = {},
const UIEditorTextMeasurer* textMeasurer = nullptr);
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,55 @@
#pragma once
#include <XCEditor/Workspace/UIEditorWorkspaceSession.h>
#include <cstdint>
#include <string>
#include <string_view>
namespace XCEngine::UI::Editor {
struct UIEditorWorkspaceLayoutSnapshot {
UIEditorWorkspaceModel workspace = {};
UIEditorWorkspaceSession session = {};
};
enum class UIEditorWorkspaceLayoutLoadCode : std::uint8_t {
None = 0,
InvalidPanelRegistry,
EmptyInput,
InvalidHeader,
UnsupportedVersion,
MissingActiveRecord,
UnexpectedEndOfInput,
InvalidNodeRecord,
InvalidSessionRecord,
InvalidWorkspace,
InvalidWorkspaceSession
};
struct UIEditorWorkspaceLayoutLoadResult {
UIEditorWorkspaceLayoutLoadCode code = UIEditorWorkspaceLayoutLoadCode::None;
std::string message = {};
UIEditorWorkspaceLayoutSnapshot snapshot = {};
[[nodiscard]] bool IsValid() const {
return code == UIEditorWorkspaceLayoutLoadCode::None;
}
};
UIEditorWorkspaceLayoutSnapshot BuildUIEditorWorkspaceLayoutSnapshot(
const UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session);
bool AreUIEditorWorkspaceLayoutSnapshotsEquivalent(
const UIEditorWorkspaceLayoutSnapshot& lhs,
const UIEditorWorkspaceLayoutSnapshot& rhs);
std::string SerializeUIEditorWorkspaceLayoutSnapshot(
const UIEditorWorkspaceLayoutSnapshot& snapshot);
UIEditorWorkspaceLayoutLoadResult DeserializeUIEditorWorkspaceLayoutSnapshot(
const UIEditorPanelRegistry& panelRegistry,
std::string_view serializedLayout);
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,94 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
namespace XCEngine::UI::Editor {
struct UIEditorWorkspaceSession;
enum class UIEditorWorkspaceNodeKind : std::uint8_t {
Panel = 0,
TabStack,
Split
};
enum class UIEditorWorkspaceSplitAxis : std::uint8_t {
Horizontal = 0,
Vertical
};
enum class UIEditorWorkspaceDockPlacement : std::uint8_t {
Center = 0,
Left,
Right,
Top,
Bottom
};
struct UIEditorWorkspacePanelState {
std::string panelId = {};
std::string title = {};
bool placeholder = false;
};
struct UIEditorWorkspaceNode {
UIEditorWorkspaceNodeKind kind = UIEditorWorkspaceNodeKind::Panel;
std::string nodeId = {};
UIEditorWorkspaceSplitAxis splitAxis = UIEditorWorkspaceSplitAxis::Horizontal;
float splitRatio = 0.5f;
std::size_t selectedTabIndex = 0u;
UIEditorWorkspacePanelState panel = {};
std::vector<UIEditorWorkspaceNode> children = {};
};
struct UIEditorWorkspaceModel {
UIEditorWorkspaceNode root = {};
std::string activePanelId = {};
};
struct UIEditorWorkspaceVisiblePanel {
std::string panelId = {};
std::string title = {};
bool active = false;
bool placeholder = false;
};
UIEditorWorkspaceNode BuildUIEditorWorkspacePanel(
std::string nodeId,
std::string panelId,
std::string title,
bool placeholder = false);
UIEditorWorkspaceNode BuildUIEditorWorkspaceSingleTabStack(
std::string nodeId,
std::string panelId,
std::string title,
bool placeholder = false);
UIEditorWorkspaceNode BuildUIEditorWorkspaceTabStack(
std::string nodeId,
std::vector<UIEditorWorkspaceNode> panels,
std::size_t selectedTabIndex = 0u);
UIEditorWorkspaceNode BuildUIEditorWorkspaceSplit(
std::string nodeId,
UIEditorWorkspaceSplitAxis axis,
float splitRatio,
UIEditorWorkspaceNode primary,
UIEditorWorkspaceNode secondary);
UIEditorWorkspaceModel CanonicalizeUIEditorWorkspaceModel(
UIEditorWorkspaceModel workspace);
bool AreUIEditorWorkspaceNodesEquivalent(
const UIEditorWorkspaceNode& lhs,
const UIEditorWorkspaceNode& rhs);
bool AreUIEditorWorkspaceModelsEquivalent(
const UIEditorWorkspaceModel& lhs,
const UIEditorWorkspaceModel& rhs);
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,60 @@
#pragma once
#include <XCEditor/Workspace/UIEditorWorkspaceModel.h>
#include <cstddef>
#include <string_view>
namespace XCEngine::UI::Editor {
struct UIEditorWorkspaceSession;
bool TryActivateUIEditorWorkspacePanel(
UIEditorWorkspaceModel& workspace,
std::string_view panelId);
bool TrySetUIEditorWorkspaceSplitRatio(
UIEditorWorkspaceModel& workspace,
std::string_view nodeId,
float splitRatio);
bool TryExtractUIEditorWorkspaceVisiblePanelNode(
UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session,
std::string_view sourceNodeId,
std::string_view panelId,
UIEditorWorkspaceNode& extractedPanel);
bool TryInsertUIEditorWorkspacePanelNodeToStack(
UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session,
UIEditorWorkspaceNode panelNode,
std::string_view targetNodeId,
std::size_t targetVisibleInsertionIndex);
bool TryDockUIEditorWorkspacePanelNodeRelative(
UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session,
UIEditorWorkspaceNode panelNode,
std::string_view targetNodeId,
UIEditorWorkspaceDockPlacement placement,
float splitRatio = 0.5f);
bool TryMoveUIEditorWorkspaceTabToStack(
UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session,
std::string_view sourceNodeId,
std::string_view panelId,
std::string_view targetNodeId,
std::size_t targetVisibleInsertionIndex);
bool TryDockUIEditorWorkspaceTabRelative(
UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session,
std::string_view sourceNodeId,
std::string_view panelId,
std::string_view targetNodeId,
UIEditorWorkspaceDockPlacement placement,
float splitRatio = 0.5f);
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,24 @@
#pragma once
#include <XCEditor/Workspace/UIEditorWorkspaceModel.h>
#include <string_view>
#include <vector>
namespace XCEngine::UI::Editor {
std::vector<UIEditorWorkspaceVisiblePanel> CollectUIEditorWorkspaceVisiblePanels(
const UIEditorWorkspaceModel& workspace);
bool ContainsUIEditorWorkspacePanel(
const UIEditorWorkspaceModel& workspace,
std::string_view panelId);
const UIEditorWorkspaceNode* FindUIEditorWorkspaceNode(
const UIEditorWorkspaceModel& workspace,
std::string_view nodeId);
const UIEditorWorkspacePanelState* FindUIEditorWorkspaceActivePanel(
const UIEditorWorkspaceModel& workspace);
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,98 @@
#pragma once
#include <XCEditor/Panels/UIEditorPanelRegistry.h>
#include <XCEditor/Workspace/UIEditorWorkspaceModel.h>
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
namespace XCEngine::UI::Editor {
struct UIEditorPanelSessionState {
std::string panelId = {};
bool open = true;
bool visible = true;
};
struct UIEditorWorkspaceSession {
std::vector<UIEditorPanelSessionState> panelStates = {};
};
enum class UIEditorWorkspaceSessionValidationCode : std::uint8_t {
None = 0,
MissingPanelState,
UnknownPanelId,
DuplicatePanelId,
ClosedPanelVisible,
NonHideablePanelHidden,
NonCloseablePanelClosed,
InvalidActivePanelId
};
struct UIEditorWorkspaceSessionValidationResult {
UIEditorWorkspaceSessionValidationCode code = UIEditorWorkspaceSessionValidationCode::None;
std::string message = {};
[[nodiscard]] bool IsValid() const {
return code == UIEditorWorkspaceSessionValidationCode::None;
}
};
UIEditorWorkspaceSession BuildDefaultUIEditorWorkspaceSession(
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWorkspaceModel& workspace);
const UIEditorPanelSessionState* FindUIEditorPanelSessionState(
const UIEditorWorkspaceSession& session,
std::string_view panelId);
UIEditorWorkspaceSessionValidationResult ValidateUIEditorWorkspaceSession(
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session);
bool AreUIEditorWorkspaceSessionsEquivalent(
const UIEditorWorkspaceSession& lhs,
const UIEditorWorkspaceSession& rhs);
std::vector<UIEditorWorkspaceVisiblePanel> CollectUIEditorWorkspaceVisiblePanels(
const UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session);
const UIEditorWorkspacePanelState* FindUIEditorWorkspaceActivePanel(
const UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session);
bool TryOpenUIEditorWorkspacePanel(
const UIEditorPanelRegistry& panelRegistry,
UIEditorWorkspaceModel& workspace,
UIEditorWorkspaceSession& session,
std::string_view panelId);
bool TryCloseUIEditorWorkspacePanel(
const UIEditorPanelRegistry& panelRegistry,
UIEditorWorkspaceModel& workspace,
UIEditorWorkspaceSession& session,
std::string_view panelId);
bool TryShowUIEditorWorkspacePanel(
const UIEditorPanelRegistry& panelRegistry,
UIEditorWorkspaceModel& workspace,
UIEditorWorkspaceSession& session,
std::string_view panelId);
bool TryHideUIEditorWorkspacePanel(
const UIEditorPanelRegistry& panelRegistry,
UIEditorWorkspaceModel& workspace,
UIEditorWorkspaceSession& session,
std::string_view panelId);
bool TryActivateUIEditorWorkspacePanel(
const UIEditorPanelRegistry& panelRegistry,
UIEditorWorkspaceModel& workspace,
UIEditorWorkspaceSession& session,
std::string_view panelId);
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,49 @@
#pragma once
#include <XCEditor/Docking/UIEditorDockHost.h>
#include <XCEditor/Docking/UIEditorDockHostInteraction.h>
#include <XCEditor/Workspace/UIEditorWorkspaceController.h>
#include <XCEditor/Workspace/UIEditorWorkspaceLayoutPersistence.h>
#include <XCEngine/UI/Types.h>
#include <string>
#include <string_view>
namespace XCEngine::UI::Editor {
struct UIEditorWorkspaceSplitterDragCorrectionState {
std::string splitNodeId = {};
UIEditorWorkspaceLayoutSnapshot baselineSnapshot = {};
Widgets::UIEditorDockHostLayout baselineDockLayout = {};
};
[[nodiscard]] bool IsUIEditorWorkspaceSplitterDragCorrectionActive(
const UIEditorWorkspaceSplitterDragCorrectionState& state);
void ResetUIEditorWorkspaceSplitterDragCorrectionState(
UIEditorWorkspaceSplitterDragCorrectionState& state);
void BeginUIEditorWorkspaceSplitterDragCorrection(
UIEditorWorkspaceSplitterDragCorrectionState& state,
std::string_view splitNodeId,
const UIEditorWorkspaceLayoutSnapshot& baselineSnapshot,
const Widgets::UIEditorDockHostLayout& baselineDockLayout);
bool TryBuildUIEditorWorkspaceSplitterDragCorrectedSnapshot(
const UIEditorWorkspaceSplitterDragCorrectionState& state,
const ::XCEngine::UI::UIPoint& pointerPosition,
bool hasPointerPosition,
const UIEditorPanelRegistry& panelRegistry,
const Widgets::UIEditorDockHostMetrics& metrics,
UIEditorWorkspaceLayoutSnapshot& outSnapshot);
bool TryApplyUIEditorWorkspaceSplitterDragCorrection(
UIEditorWorkspaceSplitterDragCorrectionState& state,
const UIEditorDockHostInteractionState& dockHostInteractionState,
const UIEditorWorkspaceLayoutSnapshot& preUpdateSnapshot,
const Widgets::UIEditorDockHostLayout& preUpdateDockLayout,
UIEditorWorkspaceController& workspaceController,
const Widgets::UIEditorDockHostMetrics& metrics);
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,41 @@
#pragma once
#include <XCEditor/Workspace/UIEditorWorkspaceSession.h>
namespace XCEngine::UI::Editor {
struct UIEditorWorkspaceExtractedPanel {
UIEditorWorkspaceNode panelNode = {};
UIEditorPanelSessionState sessionState = {};
};
bool TryExtractUIEditorWorkspaceVisiblePanel(
UIEditorWorkspaceModel& workspace,
UIEditorWorkspaceSession& session,
std::string_view sourceNodeId,
std::string_view panelId,
UIEditorWorkspaceExtractedPanel& extractedPanel);
UIEditorWorkspaceModel BuildUIEditorDetachedWorkspaceFromExtractedPanel(
std::string rootNodeId,
UIEditorWorkspaceExtractedPanel extractedPanel);
UIEditorWorkspaceSession BuildUIEditorDetachedWorkspaceSessionFromExtractedPanel(
UIEditorWorkspaceExtractedPanel extractedPanel);
bool TryInsertExtractedUIEditorWorkspacePanelToStack(
UIEditorWorkspaceModel& workspace,
UIEditorWorkspaceSession& session,
UIEditorWorkspaceExtractedPanel extractedPanel,
std::string_view targetNodeId,
std::size_t targetVisibleInsertionIndex);
bool TryDockExtractedUIEditorWorkspacePanelRelative(
UIEditorWorkspaceModel& workspace,
UIEditorWorkspaceSession& session,
UIEditorWorkspaceExtractedPanel extractedPanel,
std::string_view targetNodeId,
UIEditorWorkspaceDockPlacement placement,
float splitRatio = 0.5f);
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,37 @@
#pragma once
#include <XCEditor/Workspace/UIEditorWorkspaceModel.h>
#include <cstdint>
#include <string>
namespace XCEngine::UI::Editor {
enum class UIEditorWorkspaceValidationCode : std::uint8_t {
None = 0,
EmptyNodeId,
DuplicateNodeId,
InvalidSplitChildCount,
InvalidSplitRatio,
EmptyTabStack,
InvalidSelectedTabIndex,
NonPanelTabChild,
EmptyPanelId,
EmptyPanelTitle,
DuplicatePanelId,
InvalidActivePanelId
};
struct UIEditorWorkspaceValidationResult {
UIEditorWorkspaceValidationCode code = UIEditorWorkspaceValidationCode::None;
std::string message = {};
[[nodiscard]] bool IsValid() const {
return code == UIEditorWorkspaceValidationCode::None;
}
};
UIEditorWorkspaceValidationResult ValidateUIEditorWorkspace(
const UIEditorWorkspaceModel& workspace);
} // namespace XCEngine::UI::Editor