Build XCEditor editor shell compose foundation
This commit is contained in:
@@ -9,6 +9,7 @@ set(EDITOR_UI_UNIT_TEST_SOURCES
|
||||
test_ui_editor_menu_bar.cpp
|
||||
test_ui_editor_menu_popup.cpp
|
||||
test_ui_editor_panel_registry.cpp
|
||||
test_ui_editor_shell_compose.cpp
|
||||
test_ui_editor_collection_primitives.cpp
|
||||
test_ui_editor_dock_host.cpp
|
||||
test_ui_editor_panel_chrome.cpp
|
||||
|
||||
164
tests/UI/Editor/unit/test_ui_editor_shell_compose.cpp
Normal file
164
tests/UI/Editor/unit/test_ui_editor_shell_compose.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEngine/UI/DrawData.h>
|
||||
#include <XCEditor/Core/UIEditorShellCompose.h>
|
||||
#include <XCEditor/Core/UIEditorWorkspaceModel.h>
|
||||
#include <XCEditor/Core/UIEditorWorkspaceSession.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::UI::UIDrawCommandType;
|
||||
using XCEngine::UI::UIDrawList;
|
||||
using XCEngine::UI::UIRect;
|
||||
using XCEngine::UI::Editor::BuildDefaultUIEditorWorkspaceSession;
|
||||
using XCEngine::UI::Editor::BuildUIEditorWorkspacePanel;
|
||||
using XCEngine::UI::Editor::BuildUIEditorWorkspaceSplit;
|
||||
using XCEngine::UI::Editor::BuildUIEditorWorkspaceTabStack;
|
||||
using XCEngine::UI::Editor::BuildUIEditorShellComposeLayout;
|
||||
using XCEngine::UI::Editor::ResolveUIEditorShellComposeRequest;
|
||||
using XCEngine::UI::Editor::UIEditorPanelPresentationKind;
|
||||
using XCEngine::UI::Editor::UIEditorPanelRegistry;
|
||||
using XCEngine::UI::Editor::UIEditorShellComposeFrame;
|
||||
using XCEngine::UI::Editor::UIEditorShellComposeModel;
|
||||
using XCEngine::UI::Editor::UIEditorShellComposeState;
|
||||
using XCEngine::UI::Editor::UIEditorWorkspaceModel;
|
||||
using XCEngine::UI::Editor::UIEditorWorkspacePanelPresentationModel;
|
||||
using XCEngine::UI::Editor::UIEditorWorkspaceSplitAxis;
|
||||
using XCEngine::UI::Editor::UpdateUIEditorShellCompose;
|
||||
using XCEngine::UI::Editor::AppendUIEditorShellCompose;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorMenuBarItem;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorStatusBarSegment;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorStatusBarSlot;
|
||||
|
||||
UIEditorPanelRegistry BuildPanelRegistry() {
|
||||
UIEditorPanelRegistry registry = {};
|
||||
registry.panels = {
|
||||
{ "hierarchy", "Hierarchy", UIEditorPanelPresentationKind::Placeholder, true, true, false },
|
||||
{ "scene", "Scene", UIEditorPanelPresentationKind::ViewportShell, false, true, false },
|
||||
{ "document", "Document", UIEditorPanelPresentationKind::Placeholder, true, true, true },
|
||||
{ "inspector", "Inspector", UIEditorPanelPresentationKind::Placeholder, true, true, true }
|
||||
};
|
||||
return registry;
|
||||
}
|
||||
|
||||
UIEditorWorkspaceModel BuildWorkspace() {
|
||||
UIEditorWorkspaceModel workspace = {};
|
||||
workspace.root = BuildUIEditorWorkspaceSplit(
|
||||
"root",
|
||||
UIEditorWorkspaceSplitAxis::Horizontal,
|
||||
0.24f,
|
||||
BuildUIEditorWorkspacePanel("hierarchy-node", "hierarchy", "Hierarchy", true),
|
||||
BuildUIEditorWorkspaceSplit(
|
||||
"main",
|
||||
UIEditorWorkspaceSplitAxis::Horizontal,
|
||||
0.72f,
|
||||
BuildUIEditorWorkspaceTabStack(
|
||||
"center-tabs",
|
||||
{
|
||||
BuildUIEditorWorkspacePanel("scene-node", "scene", "Scene"),
|
||||
BuildUIEditorWorkspacePanel("document-node", "document", "Document", true)
|
||||
},
|
||||
0u),
|
||||
BuildUIEditorWorkspacePanel("inspector-node", "inspector", "Inspector", true)));
|
||||
workspace.activePanelId = "scene";
|
||||
return workspace;
|
||||
}
|
||||
|
||||
UIEditorShellComposeModel BuildShellModel() {
|
||||
UIEditorShellComposeModel model = {};
|
||||
model.menuBarItems = {
|
||||
UIEditorMenuBarItem{ "file", "File", true, 0.0f },
|
||||
UIEditorMenuBarItem{ "window", "Window", true, 0.0f },
|
||||
UIEditorMenuBarItem{ "layout", "Layout", true, 0.0f }
|
||||
};
|
||||
model.statusSegments = {
|
||||
UIEditorStatusBarSegment{ "scene", "Scene", UIEditorStatusBarSlot::Leading, {}, true, true, 72.0f },
|
||||
UIEditorStatusBarSegment{ "frame", "16.7 ms", UIEditorStatusBarSlot::Trailing, {}, true, false, 72.0f }
|
||||
};
|
||||
|
||||
UIEditorWorkspacePanelPresentationModel presentation = {};
|
||||
presentation.panelId = "scene";
|
||||
presentation.kind = UIEditorPanelPresentationKind::ViewportShell;
|
||||
presentation.viewportShellModel.spec.chrome.title = "Scene";
|
||||
presentation.viewportShellModel.spec.chrome.showTopBar = true;
|
||||
presentation.viewportShellModel.spec.chrome.showBottomBar = true;
|
||||
presentation.viewportShellModel.frame.hasTexture = false;
|
||||
presentation.viewportShellModel.frame.statusText = "Viewport frame";
|
||||
model.workspacePresentations = { presentation };
|
||||
return model;
|
||||
}
|
||||
|
||||
bool ContainsTextCommand(const UIDrawList& drawList, std::string_view text) {
|
||||
for (const auto& command : drawList.GetCommands()) {
|
||||
if (command.type == UIDrawCommandType::Text && command.text == text) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(UIEditorShellComposeTest, LayoutAllocatesMenuWorkspaceAndStatusBandsWithoutOverlap) {
|
||||
const UIEditorShellComposeModel model = BuildShellModel();
|
||||
|
||||
const auto layout = BuildUIEditorShellComposeLayout(
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
model.menuBarItems,
|
||||
model.statusSegments);
|
||||
|
||||
EXPECT_GT(layout.menuBarRect.height, 0.0f);
|
||||
EXPECT_GT(layout.workspaceRect.height, 0.0f);
|
||||
EXPECT_GT(layout.statusBarRect.height, 0.0f);
|
||||
EXPECT_LE(layout.menuBarRect.y + layout.menuBarRect.height, layout.workspaceRect.y);
|
||||
EXPECT_LE(layout.workspaceRect.y + layout.workspaceRect.height, layout.statusBarRect.y);
|
||||
EXPECT_FLOAT_EQ(layout.contentRect.x, 12.0f);
|
||||
EXPECT_FLOAT_EQ(layout.contentRect.y, 12.0f);
|
||||
}
|
||||
|
||||
TEST(UIEditorShellComposeTest, ResolveRequestRoutesWorkspaceComposeThroughWorkspaceBand) {
|
||||
const auto registry = BuildPanelRegistry();
|
||||
const auto workspace = BuildWorkspace();
|
||||
const auto session = BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
const UIEditorShellComposeModel model = BuildShellModel();
|
||||
|
||||
const auto request = ResolveUIEditorShellComposeRequest(
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model);
|
||||
|
||||
EXPECT_FLOAT_EQ(request.workspaceRequest.dockHostLayout.bounds.x, request.layout.workspaceRect.x);
|
||||
EXPECT_FLOAT_EQ(request.workspaceRequest.dockHostLayout.bounds.y, request.layout.workspaceRect.y);
|
||||
EXPECT_FLOAT_EQ(request.workspaceRequest.dockHostLayout.bounds.width, request.layout.workspaceRect.width);
|
||||
EXPECT_FLOAT_EQ(request.workspaceRequest.dockHostLayout.bounds.height, request.layout.workspaceRect.height);
|
||||
ASSERT_EQ(request.workspaceRequest.viewportRequests.size(), 1u);
|
||||
EXPECT_EQ(request.workspaceRequest.viewportRequests.front().panelId, "scene");
|
||||
}
|
||||
|
||||
TEST(UIEditorShellComposeTest, AppendComposeEmitsMenuStatusAndWorkspaceCommandsTogether) {
|
||||
const auto registry = BuildPanelRegistry();
|
||||
const auto workspace = BuildWorkspace();
|
||||
const auto session = BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
const UIEditorShellComposeModel model = BuildShellModel();
|
||||
|
||||
UIEditorShellComposeState state = {};
|
||||
const UIEditorShellComposeFrame frame = UpdateUIEditorShellCompose(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{});
|
||||
|
||||
UIDrawList drawList("EditorShellCompose");
|
||||
AppendUIEditorShellCompose(drawList, frame, model, state);
|
||||
|
||||
EXPECT_GT(drawList.GetCommandCount(), 20u);
|
||||
EXPECT_TRUE(ContainsTextCommand(drawList, "File"));
|
||||
EXPECT_TRUE(ContainsTextCommand(drawList, "Scene"));
|
||||
EXPECT_TRUE(ContainsTextCommand(drawList, "16.7 ms"));
|
||||
}
|
||||
Reference in New Issue
Block a user