Unify dock leaves around single-tab stacks

This commit is contained in:
2026-04-10 21:50:31 +08:00
parent b187c8970b
commit 977a4cf2a4
14 changed files with 258 additions and 195 deletions

View File

@@ -22,6 +22,55 @@ bool IsValidSplitRatio(float value) {
return std::isfinite(value) && value > 0.0f && value < 1.0f;
}
std::string BuildSingleTabPanelNodeId(std::string_view stackNodeId) {
if (stackNodeId.empty()) {
return "single-tab-panel";
}
return std::string(stackNodeId) + "__panel";
}
UIEditorWorkspaceNode WrapStandalonePanelAsTabStack(UIEditorWorkspaceNode panelNode) {
UIEditorWorkspaceNode panelChild = std::move(panelNode);
const std::string stackNodeId = panelChild.nodeId;
panelChild.nodeId = BuildSingleTabPanelNodeId(stackNodeId);
UIEditorWorkspaceNode tabStack = {};
tabStack.kind = UIEditorWorkspaceNodeKind::TabStack;
tabStack.nodeId = stackNodeId;
tabStack.selectedTabIndex = 0u;
tabStack.children.push_back(std::move(panelChild));
return tabStack;
}
void CanonicalizeNodeRecursive(
UIEditorWorkspaceNode& node,
bool allowStandalonePanelLeaf) {
if (node.kind == UIEditorWorkspaceNodeKind::Panel) {
if (!allowStandalonePanelLeaf) {
node = WrapStandalonePanelAsTabStack(std::move(node));
}
return;
}
for (UIEditorWorkspaceNode& child : node.children) {
CanonicalizeNodeRecursive(
child,
node.kind == UIEditorWorkspaceNodeKind::TabStack);
}
if (node.kind == UIEditorWorkspaceNodeKind::TabStack &&
!node.children.empty() &&
node.selectedTabIndex >= node.children.size()) {
node.selectedTabIndex = node.children.size() - 1u;
}
if (node.kind == UIEditorWorkspaceNodeKind::Split &&
node.children.size() == 1u) {
node = std::move(node.children.front());
}
}
const UIEditorPanelDescriptor& RequirePanelDescriptor(
const UIEditorPanelRegistry& registry,
std::string_view panelId) {
@@ -274,7 +323,7 @@ UIEditorWorkspaceModel BuildDefaultEditorShellWorkspaceModel() {
RequirePanelDescriptor(registry, "editor-foundation-root");
UIEditorWorkspaceModel workspace = {};
workspace.root = BuildUIEditorWorkspacePanel(
workspace.root = BuildUIEditorWorkspaceSingleTabStack(
"editor-foundation-root-node",
rootPanel.panelId,
rootPanel.defaultTitle,
@@ -297,6 +346,22 @@ UIEditorWorkspaceNode BuildUIEditorWorkspacePanel(
return node;
}
UIEditorWorkspaceNode BuildUIEditorWorkspaceSingleTabStack(
std::string nodeId,
std::string panelId,
std::string title,
bool placeholder) {
UIEditorWorkspaceNode panel = BuildUIEditorWorkspacePanel(
BuildSingleTabPanelNodeId(nodeId),
std::move(panelId),
std::move(title),
placeholder);
return BuildUIEditorWorkspaceTabStack(
std::move(nodeId),
{ std::move(panel) },
0u);
}
UIEditorWorkspaceNode BuildUIEditorWorkspaceTabStack(
std::string nodeId,
std::vector<UIEditorWorkspaceNode> panels,
@@ -345,6 +410,12 @@ UIEditorWorkspaceValidationResult ValidateUIEditorWorkspace(
return {};
}
UIEditorWorkspaceModel CanonicalizeUIEditorWorkspaceModel(
UIEditorWorkspaceModel workspace) {
CanonicalizeNodeRecursive(workspace.root, false);
return workspace;
}
std::vector<UIEditorWorkspaceVisiblePanel> CollectUIEditorWorkspaceVisiblePanels(
const UIEditorWorkspaceModel& workspace) {
std::vector<UIEditorWorkspaceVisiblePanel> visiblePanels = {};