Center tab labels and unify dock cursor resolution

This commit is contained in:
2026-04-11 17:37:13 +08:00
parent 2958dcc491
commit 443c56ed08
6 changed files with 197 additions and 7 deletions

View File

@@ -27,6 +27,8 @@ using XCEngine::UI::Editor::Widgets::AppendUIEditorDockHostForeground;
using XCEngine::UI::Editor::Widgets::BuildUIEditorDockHostLayout;
using XCEngine::UI::Editor::Widgets::FindUIEditorDockHostSplitterLayout;
using XCEngine::UI::Editor::Widgets::HitTestUIEditorDockHost;
using XCEngine::UI::Editor::Widgets::ResolveUIEditorDockHostCursorKind;
using XCEngine::UI::Editor::Widgets::UIEditorDockHostCursorKind;
using XCEngine::UI::Editor::Widgets::UIEditorDockHostHitTarget;
using XCEngine::UI::Editor::Widgets::UIEditorDockHostHitTargetKind;
using XCEngine::UI::Editor::Widgets::UIEditorDockHostLayout;
@@ -210,6 +212,77 @@ TEST(UIEditorDockHostTest, BackgroundAndForegroundEmitStableCompositeCommands) {
EXPECT_GT(foreground.GetCommandCount(), 10u);
}
TEST(UIEditorDockHostTest, CursorFallsBackToArrowWhenNoSplitterIsHoveredOrActive) {
const UIEditorPanelRegistry registry = BuildPanelRegistry();
const UIEditorWorkspaceModel workspace = BuildWorkspace();
const UIEditorWorkspaceSession session =
BuildDefaultUIEditorWorkspaceSession(registry, workspace);
const UIEditorDockHostLayout layout = BuildUIEditorDockHostLayout(
UIRect(0.0f, 0.0f, 800.0f, 600.0f),
registry,
workspace,
session);
EXPECT_EQ(ResolveUIEditorDockHostCursorKind(layout), UIEditorDockHostCursorKind::Arrow);
}
TEST(UIEditorDockHostTest, CursorUsesHoveredSplitterAxisWhenPointerRestsOnHandle) {
const UIEditorPanelRegistry registry = BuildPanelRegistry();
const UIEditorWorkspaceModel workspace = BuildWorkspace();
const UIEditorWorkspaceSession session =
BuildDefaultUIEditorWorkspaceSession(registry, workspace);
UIEditorDockHostState state = {};
state.hoveredTarget = UIEditorDockHostHitTarget{
UIEditorDockHostHitTargetKind::SplitterHandle,
"root-split",
{},
UIEditorTabStripInvalidIndex
};
const UIEditorDockHostLayout horizontalLayout = BuildUIEditorDockHostLayout(
UIRect(0.0f, 0.0f, 800.0f, 600.0f),
registry,
workspace,
session,
state);
EXPECT_EQ(ResolveUIEditorDockHostCursorKind(horizontalLayout), UIEditorDockHostCursorKind::ResizeEW);
state.hoveredTarget.nodeId = "right-split";
const UIEditorDockHostLayout verticalLayout = BuildUIEditorDockHostLayout(
UIRect(0.0f, 0.0f, 800.0f, 600.0f),
registry,
workspace,
session,
state);
EXPECT_EQ(ResolveUIEditorDockHostCursorKind(verticalLayout), UIEditorDockHostCursorKind::ResizeNS);
}
TEST(UIEditorDockHostTest, CursorPrefersActiveSplitterOverHoveredSplitter) {
const UIEditorPanelRegistry registry = BuildPanelRegistry();
const UIEditorWorkspaceModel workspace = BuildWorkspace();
const UIEditorWorkspaceSession session =
BuildDefaultUIEditorWorkspaceSession(registry, workspace);
UIEditorDockHostState state = {};
state.hoveredTarget = UIEditorDockHostHitTarget{
UIEditorDockHostHitTargetKind::SplitterHandle,
"root-split",
{},
UIEditorTabStripInvalidIndex
};
state.activeSplitterNodeId = "right-split";
const UIEditorDockHostLayout layout = BuildUIEditorDockHostLayout(
UIRect(0.0f, 0.0f, 800.0f, 600.0f),
registry,
workspace,
session,
state);
EXPECT_EQ(ResolveUIEditorDockHostCursorKind(layout), UIEditorDockHostCursorKind::ResizeNS);
}
TEST(UIEditorDockHostTest, ForegroundDrawsUnifiedTabTitlesAcrossAllLeafStacks) {
const UIEditorPanelRegistry registry = BuildPanelRegistry();
const UIEditorWorkspaceModel workspace = BuildWorkspace();

View File

@@ -173,4 +173,41 @@ TEST(UIEditorTabStripTest, BackgroundAndForegroundEmitStableChromeCommands) {
EXPECT_EQ(foregroundCommands[6].text, "Document B");
}
TEST(UIEditorTabStripTest, ForegroundCentersTabLabelsWithinHeaderContentArea) {
UIEditorTabStripMetrics metrics = {};
metrics.layoutMetrics.headerHeight = 22.0f;
metrics.layoutMetrics.tabMinWidth = 68.0f;
metrics.layoutMetrics.tabHorizontalPadding = 8.0f;
metrics.layoutMetrics.tabGap = 1.0f;
metrics.labelInsetX = 8.0f;
const std::vector<UIEditorTabStripItem> items = {
{ "doc-a", "Scene", true, 30.0f },
{ "doc-b", "Game", true, 24.0f }
};
UIEditorTabStripState state = {};
state.selectedIndex = 0u;
const UIEditorTabStripLayout layout =
BuildUIEditorTabStripLayout(UIRect(10.0f, 20.0f, 220.0f, 120.0f), items, state, metrics);
UIDrawList foreground("TabStripForeground");
AppendUIEditorTabStripForeground(foreground, layout, items, state, {}, metrics);
const auto& commands = foreground.GetCommands();
ASSERT_EQ(commands[3].type, UIDrawCommandType::Text);
ASSERT_EQ(commands[6].type, UIDrawCommandType::Text);
const float padding = 8.0f;
const float firstExpectedX =
layout.tabHeaderRects[0].x + padding +
((layout.tabHeaderRects[0].width - padding * 2.0f) - items[0].desiredHeaderLabelWidth) * 0.5f;
const float secondExpectedX =
layout.tabHeaderRects[1].x + padding +
((layout.tabHeaderRects[1].width - padding * 2.0f) - items[1].desiredHeaderLabelWidth) * 0.5f;
EXPECT_FLOAT_EQ(commands[3].position.x, firstExpectedX);
EXPECT_FLOAT_EQ(commands[6].position.x, secondExpectedX);
}
} // namespace