refactor(new_editor): unify panel input and rename primitives
This commit is contained in:
@@ -9,6 +9,7 @@ set(EDITOR_UI_UNIT_TEST_SOURCES
|
||||
test_ui_editor_menu_popup.cpp
|
||||
test_ui_editor_panel_content_host.cpp
|
||||
test_ui_editor_panel_host_lifecycle.cpp
|
||||
test_ui_editor_panel_input_filter.cpp
|
||||
test_ui_editor_property_grid.cpp
|
||||
test_ui_editor_property_grid_interaction.cpp
|
||||
test_ui_editor_shell_compose.cpp
|
||||
@@ -47,6 +48,7 @@ set(EDITOR_UI_UNIT_TEST_SOURCES
|
||||
test_ui_editor_status_bar.cpp
|
||||
test_ui_editor_tab_strip.cpp
|
||||
test_ui_editor_tab_strip_interaction.cpp
|
||||
test_ui_editor_tree_panel_behavior.cpp
|
||||
test_ui_editor_tree_view.cpp
|
||||
test_ui_editor_tree_view_interaction.cpp
|
||||
test_ui_editor_viewport_input_bridge.cpp
|
||||
|
||||
@@ -7,10 +7,14 @@
|
||||
namespace {
|
||||
|
||||
using XCEngine::Input::KeyCode;
|
||||
using XCEngine::UI::UIDrawList;
|
||||
using XCEngine::UI::UIDrawCommandType;
|
||||
using XCEngine::UI::UIInputEvent;
|
||||
using XCEngine::UI::UIInputEventType;
|
||||
using XCEngine::UI::UIRect;
|
||||
using XCEngine::UI::Editor::AppendUIEditorInlineRenameSession;
|
||||
using XCEngine::UI::Editor::UIEditorInlineRenameSessionRequest;
|
||||
using XCEngine::UI::Editor::UIEditorInlineRenameSessionFrame;
|
||||
using XCEngine::UI::Editor::UIEditorInlineRenameSessionState;
|
||||
using XCEngine::UI::Editor::UpdateUIEditorInlineRenameSession;
|
||||
|
||||
@@ -122,3 +126,19 @@ TEST(UIEditorInlineRenameSessionTest, FocusLostCommitsEditedValue) {
|
||||
EXPECT_EQ(frame.result.valueAfter, "CameraX");
|
||||
EXPECT_FALSE(state.active);
|
||||
}
|
||||
|
||||
TEST(UIEditorInlineRenameSessionTest, AppendUsesActiveSessionStateToEmitTextFieldCommands) {
|
||||
UIEditorInlineRenameSessionState state = {};
|
||||
UIDrawList drawList("InlineRename");
|
||||
const UIEditorInlineRenameSessionFrame inactiveFrame = {};
|
||||
|
||||
AppendUIEditorInlineRenameSession(drawList, inactiveFrame, state);
|
||||
EXPECT_TRUE(drawList.Empty());
|
||||
|
||||
const UIEditorInlineRenameSessionFrame activeFrame =
|
||||
UpdateUIEditorInlineRenameSession(state, MakeRequest(true), {});
|
||||
AppendUIEditorInlineRenameSession(drawList, activeFrame, state);
|
||||
|
||||
ASSERT_FALSE(drawList.Empty());
|
||||
EXPECT_EQ(drawList.GetCommands().front().type, UIDrawCommandType::FilledRect);
|
||||
}
|
||||
|
||||
95
tests/UI/Editor/unit/test_ui_editor_panel_input_filter.cpp
Normal file
95
tests/UI/Editor/unit/test_ui_editor_panel_input_filter.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEditor/Foundation/UIEditorPanelInputFilter.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::UI::Editor::FilterUIEditorPanelInputEvents;
|
||||
using XCEngine::UI::Editor::UIEditorPanelInputFilterOptions;
|
||||
using ::XCEngine::UI::UIInputEvent;
|
||||
using ::XCEngine::UI::UIInputEventType;
|
||||
using ::XCEngine::UI::UIPoint;
|
||||
using ::XCEngine::UI::UIPointerButton;
|
||||
using ::XCEngine::UI::UIRect;
|
||||
|
||||
UIInputEvent MakePointerMove(float x, float y) {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::PointerMove;
|
||||
event.position = UIPoint(x, y);
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakePointerButtonDown(float x, float y) {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::PointerButtonDown;
|
||||
event.position = UIPoint(x, y);
|
||||
event.pointerButton = UIPointerButton::Left;
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakeKeyDown() {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::KeyDown;
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakeFocusLost() {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::FocusLost;
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakePointerLeave() {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::PointerLeave;
|
||||
return event;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(UIEditorPanelInputFilterTests, FiltersPointerByBoundsAndPreservesKeyboardAndFocusChannels) {
|
||||
const std::vector<UIInputEvent> filtered =
|
||||
FilterUIEditorPanelInputEvents(
|
||||
UIRect(0.0f, 0.0f, 100.0f, 100.0f),
|
||||
{
|
||||
MakePointerMove(20.0f, 20.0f),
|
||||
MakePointerButtonDown(140.0f, 20.0f),
|
||||
MakeKeyDown(),
|
||||
MakeFocusLost(),
|
||||
MakePointerLeave()
|
||||
},
|
||||
UIEditorPanelInputFilterOptions{
|
||||
.allowPointerInBounds = true,
|
||||
.allowPointerWhileCaptured = false,
|
||||
.allowKeyboardInput = true,
|
||||
.allowFocusEvents = true,
|
||||
.includePointerLeave = true
|
||||
});
|
||||
|
||||
ASSERT_EQ(filtered.size(), 4u);
|
||||
EXPECT_EQ(filtered[0].type, UIInputEventType::PointerMove);
|
||||
EXPECT_EQ(filtered[1].type, UIInputEventType::KeyDown);
|
||||
EXPECT_EQ(filtered[2].type, UIInputEventType::FocusLost);
|
||||
EXPECT_EQ(filtered[3].type, UIInputEventType::PointerLeave);
|
||||
}
|
||||
|
||||
TEST(UIEditorPanelInputFilterTests, CapturedPointerEventsBypassBoundsWhenEnabled) {
|
||||
const std::vector<UIInputEvent> filtered =
|
||||
FilterUIEditorPanelInputEvents(
|
||||
UIRect(0.0f, 0.0f, 100.0f, 100.0f),
|
||||
{
|
||||
MakePointerMove(140.0f, 20.0f),
|
||||
MakePointerButtonDown(180.0f, 32.0f)
|
||||
},
|
||||
UIEditorPanelInputFilterOptions{
|
||||
.allowPointerInBounds = false,
|
||||
.allowPointerWhileCaptured = true,
|
||||
.allowKeyboardInput = false,
|
||||
.allowFocusEvents = false,
|
||||
.includePointerLeave = false
|
||||
});
|
||||
|
||||
ASSERT_EQ(filtered.size(), 2u);
|
||||
EXPECT_EQ(filtered[0].type, UIInputEventType::PointerMove);
|
||||
EXPECT_EQ(filtered[1].type, UIInputEventType::PointerButtonDown);
|
||||
}
|
||||
177
tests/UI/Editor/unit/test_ui_editor_tree_panel_behavior.cpp
Normal file
177
tests/UI/Editor/unit/test_ui_editor_tree_panel_behavior.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEditor/Collections/UIEditorTreePanelBehavior.h>
|
||||
|
||||
#include <XCEngine/UI/Widgets/UIExpansionModel.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
|
||||
namespace TreeDrag = XCEngine::UI::Editor::Collections::TreeDragDrop;
|
||||
namespace Widgets = XCEngine::UI::Editor::Widgets;
|
||||
|
||||
using XCEngine::UI::Editor::BuildUIEditorTreePanelInlineRenameBounds;
|
||||
using XCEngine::UI::Editor::BuildUIEditorTreePanelInteractionInputEvents;
|
||||
using XCEngine::UI::Editor::FilterUIEditorTreePanelInputEvents;
|
||||
using XCEngine::UI::Editor::FilterUIEditorTreePanelPointerInputEvents;
|
||||
using XCEngine::UI::Editor::FindUIEditorTreePanelVisibleItemIndex;
|
||||
using XCEngine::UI::Editor::UIEditorTreePanelInputFilterOptions;
|
||||
using ::XCEngine::UI::UIInputEvent;
|
||||
using ::XCEngine::UI::UIInputEventType;
|
||||
using ::XCEngine::UI::UIPoint;
|
||||
using ::XCEngine::UI::UIPointerButton;
|
||||
using ::XCEngine::UI::UIRect;
|
||||
|
||||
UIInputEvent MakePointerMove(float x, float y) {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::PointerMove;
|
||||
event.position = UIPoint(x, y);
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakePointerButtonDown(float x, float y) {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::PointerButtonDown;
|
||||
event.position = UIPoint(x, y);
|
||||
event.pointerButton = UIPointerButton::Left;
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakePointerButtonUp(float x, float y) {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::PointerButtonUp;
|
||||
event.position = UIPoint(x, y);
|
||||
event.pointerButton = UIPointerButton::Left;
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakeKeyDown() {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::KeyDown;
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakeFocusLost() {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::FocusLost;
|
||||
return event;
|
||||
}
|
||||
|
||||
struct TreeFixture {
|
||||
std::vector<Widgets::UIEditorTreeViewItem> items = {};
|
||||
::XCEngine::UI::Widgets::UIExpansionModel expansion = {};
|
||||
Widgets::UIEditorTreeViewLayout layout = {};
|
||||
};
|
||||
|
||||
TreeFixture BuildTreeFixture() {
|
||||
TreeFixture fixture = {};
|
||||
fixture.items = {
|
||||
Widgets::UIEditorTreeViewItem{ .itemId = "root", .label = "Root" },
|
||||
Widgets::UIEditorTreeViewItem{ .itemId = "child", .label = "Child", .depth = 1u }
|
||||
};
|
||||
fixture.expansion.Expand("root");
|
||||
fixture.layout = Widgets::BuildUIEditorTreeViewLayout(
|
||||
UIRect(0.0f, 0.0f, 240.0f, 120.0f),
|
||||
fixture.items,
|
||||
fixture.expansion);
|
||||
return fixture;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(UIEditorTreePanelBehaviorTests, FilterPanelInputHonorsBoundsAndPanelActivity) {
|
||||
const std::vector<UIInputEvent> filtered =
|
||||
FilterUIEditorTreePanelInputEvents(
|
||||
UIRect(0.0f, 0.0f, 100.0f, 100.0f),
|
||||
{
|
||||
MakePointerMove(40.0f, 40.0f),
|
||||
MakePointerMove(140.0f, 40.0f),
|
||||
MakeKeyDown(),
|
||||
MakeFocusLost()
|
||||
},
|
||||
UIEditorTreePanelInputFilterOptions{
|
||||
.allowInteraction = true,
|
||||
.panelActive = true,
|
||||
.captureActive = false
|
||||
});
|
||||
|
||||
ASSERT_EQ(filtered.size(), 3u);
|
||||
EXPECT_EQ(filtered[0].type, UIInputEventType::PointerMove);
|
||||
EXPECT_EQ(filtered[1].type, UIInputEventType::KeyDown);
|
||||
EXPECT_EQ(filtered[2].type, UIInputEventType::FocusLost);
|
||||
}
|
||||
|
||||
TEST(UIEditorTreePanelBehaviorTests, FilterPointerInputSuppressesPointerOnlyEvents) {
|
||||
const std::vector<UIInputEvent> filtered =
|
||||
FilterUIEditorTreePanelPointerInputEvents(
|
||||
{
|
||||
MakePointerMove(10.0f, 10.0f),
|
||||
MakePointerButtonDown(10.0f, 10.0f),
|
||||
MakeKeyDown(),
|
||||
MakeFocusLost()
|
||||
},
|
||||
true);
|
||||
|
||||
ASSERT_EQ(filtered.size(), 2u);
|
||||
EXPECT_EQ(filtered[0].type, UIInputEventType::KeyDown);
|
||||
EXPECT_EQ(filtered[1].type, UIInputEventType::FocusLost);
|
||||
}
|
||||
|
||||
TEST(UIEditorTreePanelBehaviorTests, BuildInteractionInputEventsSuppressesDragGesturePreview) {
|
||||
const TreeFixture fixture = BuildTreeFixture();
|
||||
TreeDrag::State dragState = {};
|
||||
ASSERT_GE(fixture.layout.rowRects.size(), 2u);
|
||||
const UIRect sourceRow = fixture.layout.rowRects[1];
|
||||
const UIRect targetRow = fixture.layout.rowRects[0];
|
||||
|
||||
const std::vector<UIInputEvent> filtered =
|
||||
BuildUIEditorTreePanelInteractionInputEvents(
|
||||
dragState,
|
||||
fixture.layout,
|
||||
fixture.items,
|
||||
{
|
||||
MakePointerButtonDown(
|
||||
sourceRow.x + 12.0f,
|
||||
sourceRow.y + sourceRow.height * 0.5f),
|
||||
MakePointerMove(
|
||||
sourceRow.x + 24.0f,
|
||||
sourceRow.y + sourceRow.height * 0.5f),
|
||||
MakePointerMove(
|
||||
targetRow.x + 12.0f,
|
||||
targetRow.y + targetRow.height * 0.5f),
|
||||
MakePointerButtonUp(
|
||||
targetRow.x + 12.0f,
|
||||
targetRow.y + targetRow.height * 0.5f),
|
||||
MakeFocusLost()
|
||||
});
|
||||
|
||||
ASSERT_EQ(filtered.size(), 2u);
|
||||
EXPECT_EQ(filtered[0].type, UIInputEventType::PointerButtonDown);
|
||||
EXPECT_EQ(filtered[1].type, UIInputEventType::FocusLost);
|
||||
}
|
||||
|
||||
TEST(UIEditorTreePanelBehaviorTests, VisibleIndexAndRenameBoundsFollowCurrentLayout) {
|
||||
const TreeFixture fixture = BuildTreeFixture();
|
||||
const Widgets::UIEditorTextFieldMetrics hostedMetrics = {
|
||||
.valueTextInsetX = 8.0f
|
||||
};
|
||||
|
||||
const std::size_t visibleIndex =
|
||||
FindUIEditorTreePanelVisibleItemIndex(fixture.layout, fixture.items, "child");
|
||||
ASSERT_EQ(visibleIndex, 1u);
|
||||
|
||||
const UIRect bounds =
|
||||
BuildUIEditorTreePanelInlineRenameBounds(
|
||||
fixture.layout,
|
||||
fixture.items,
|
||||
"child",
|
||||
hostedMetrics);
|
||||
const UIRect& rowRect = fixture.layout.rowRects[visibleIndex];
|
||||
const UIRect& labelRect = fixture.layout.labelRects[visibleIndex];
|
||||
|
||||
EXPECT_FLOAT_EQ(bounds.x, (std::max)(rowRect.x, labelRect.x - hostedMetrics.valueTextInsetX));
|
||||
EXPECT_FLOAT_EQ(bounds.y, rowRect.y);
|
||||
EXPECT_FLOAT_EQ(bounds.height, rowRect.height);
|
||||
EXPECT_FLOAT_EQ(bounds.width, (std::max)(120.0f, rowRect.x + rowRect.width - 8.0f - bounds.x));
|
||||
}
|
||||
Reference in New Issue
Block a user