Lay groundwork for detached editor windows

This commit is contained in:
2026-04-14 15:07:52 +08:00
parent 804e5138d7
commit 3f871a4f45
21 changed files with 1820 additions and 97 deletions

View File

@@ -31,10 +31,13 @@ struct UIEditorDockHostInteractionResult {
bool consumed = false;
bool commandExecuted = false;
bool layoutChanged = false;
bool detachRequested = false;
bool requestPointerCapture = false;
bool releasePointerCapture = false;
Widgets::UIEditorDockHostHitTarget hitTarget = {};
std::string activeSplitterNodeId = {};
std::string detachedNodeId = {};
std::string detachedPanelId = {};
UIEditorWorkspaceCommandResult commandResult = {};
UIEditorWorkspaceLayoutOperationResult layoutResult = {};
};

View File

@@ -0,0 +1,91 @@
#pragma once
#include <XCEditor/Shell/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,62 @@
#pragma once
#include <XCEditor/Shell/UIEditorPanelRegistry.h>
#include <XCEditor/Shell/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,
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

@@ -150,6 +150,28 @@ bool TryReorderUIEditorWorkspaceTab(
std::string_view panelId,
std::size_t targetVisibleInsertionIndex);
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,

View File

@@ -0,0 +1,41 @@
#pragma once
#include <XCEditor/Shell/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