Add XCUI command routing and widget state models
This commit is contained in:
@@ -6,6 +6,8 @@ set(UI_TEST_SOURCES
|
||||
test_ui_core.cpp
|
||||
test_ui_editor_collection_primitives.cpp
|
||||
test_ui_expansion_model.cpp
|
||||
test_ui_keyboard_navigation_model.cpp
|
||||
test_ui_property_edit_model.cpp
|
||||
test_layout_engine.cpp
|
||||
test_ui_selection_model.cpp
|
||||
test_ui_runtime.cpp
|
||||
|
||||
101
tests/Core/UI/test_ui_keyboard_navigation_model.cpp
Normal file
101
tests/Core/UI/test_ui_keyboard_navigation_model.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEngine/UI/Widgets/UIKeyboardNavigationModel.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::UI::Widgets::UIKeyboardNavigationModel;
|
||||
|
||||
TEST(UIKeyboardNavigationModelTest, EmptyModelStartsWithoutCurrentIndexOrAnchor) {
|
||||
UIKeyboardNavigationModel navigation = {};
|
||||
|
||||
EXPECT_EQ(navigation.GetItemCount(), 0u);
|
||||
EXPECT_FALSE(navigation.HasCurrentIndex());
|
||||
EXPECT_EQ(navigation.GetCurrentIndex(), UIKeyboardNavigationModel::InvalidIndex);
|
||||
EXPECT_FALSE(navigation.HasSelectionAnchor());
|
||||
EXPECT_EQ(navigation.GetSelectionAnchorIndex(), UIKeyboardNavigationModel::InvalidIndex);
|
||||
EXPECT_FALSE(navigation.MoveNext());
|
||||
EXPECT_FALSE(navigation.MovePrevious());
|
||||
EXPECT_FALSE(navigation.MoveHome());
|
||||
EXPECT_FALSE(navigation.MoveEnd());
|
||||
}
|
||||
|
||||
TEST(UIKeyboardNavigationModelTest, SetCurrentIndexAndDirectionalMovesTrackCurrentIndexAndAnchor) {
|
||||
UIKeyboardNavigationModel navigation = {};
|
||||
ASSERT_TRUE(navigation.SetItemCount(4u));
|
||||
|
||||
EXPECT_TRUE(navigation.SetCurrentIndex(1u));
|
||||
EXPECT_EQ(navigation.GetCurrentIndex(), 1u);
|
||||
EXPECT_EQ(navigation.GetSelectionAnchorIndex(), 1u);
|
||||
|
||||
EXPECT_TRUE(navigation.MoveNext());
|
||||
EXPECT_EQ(navigation.GetCurrentIndex(), 2u);
|
||||
EXPECT_EQ(navigation.GetSelectionAnchorIndex(), 2u);
|
||||
|
||||
EXPECT_TRUE(navigation.MoveEnd());
|
||||
EXPECT_EQ(navigation.GetCurrentIndex(), 3u);
|
||||
EXPECT_EQ(navigation.GetSelectionAnchorIndex(), 3u);
|
||||
EXPECT_FALSE(navigation.MoveNext());
|
||||
|
||||
EXPECT_TRUE(navigation.MoveHome());
|
||||
EXPECT_EQ(navigation.GetCurrentIndex(), 0u);
|
||||
EXPECT_EQ(navigation.GetSelectionAnchorIndex(), 0u);
|
||||
EXPECT_FALSE(navigation.MovePrevious());
|
||||
}
|
||||
|
||||
TEST(UIKeyboardNavigationModelTest, MovePreviousAndEndSeedNavigationWhenCurrentIndexIsUnset) {
|
||||
UIKeyboardNavigationModel navigation = {};
|
||||
ASSERT_TRUE(navigation.SetItemCount(5u));
|
||||
|
||||
EXPECT_TRUE(navigation.MovePrevious());
|
||||
EXPECT_EQ(navigation.GetCurrentIndex(), 4u);
|
||||
EXPECT_EQ(navigation.GetSelectionAnchorIndex(), 4u);
|
||||
|
||||
EXPECT_TRUE(navigation.ClearCurrentIndex());
|
||||
EXPECT_TRUE(navigation.ClearSelectionAnchor());
|
||||
EXPECT_FALSE(navigation.HasCurrentIndex());
|
||||
EXPECT_FALSE(navigation.HasSelectionAnchor());
|
||||
|
||||
EXPECT_TRUE(navigation.MoveEnd());
|
||||
EXPECT_EQ(navigation.GetCurrentIndex(), 4u);
|
||||
EXPECT_EQ(navigation.GetSelectionAnchorIndex(), 4u);
|
||||
}
|
||||
|
||||
TEST(UIKeyboardNavigationModelTest, ExplicitAnchorCanBePreservedUntilNavigationCollapsesIt) {
|
||||
UIKeyboardNavigationModel navigation = {};
|
||||
ASSERT_TRUE(navigation.SetItemCount(6u));
|
||||
|
||||
EXPECT_TRUE(navigation.SetSelectionAnchorIndex(1u));
|
||||
EXPECT_TRUE(navigation.SetCurrentIndex(4u, false));
|
||||
EXPECT_EQ(navigation.GetCurrentIndex(), 4u);
|
||||
EXPECT_EQ(navigation.GetSelectionAnchorIndex(), 1u);
|
||||
|
||||
EXPECT_TRUE(navigation.MovePrevious());
|
||||
EXPECT_EQ(navigation.GetCurrentIndex(), 3u);
|
||||
EXPECT_EQ(navigation.GetSelectionAnchorIndex(), 3u);
|
||||
}
|
||||
|
||||
TEST(UIKeyboardNavigationModelTest, ItemCountChangesClampCurrentIndexAndSelectionAnchor) {
|
||||
UIKeyboardNavigationModel navigation = {};
|
||||
ASSERT_TRUE(navigation.SetItemCount(5u));
|
||||
ASSERT_TRUE(navigation.SetSelectionAnchorIndex(3u));
|
||||
ASSERT_TRUE(navigation.SetCurrentIndex(4u, false));
|
||||
|
||||
EXPECT_TRUE(navigation.SetItemCount(4u));
|
||||
EXPECT_EQ(navigation.GetCurrentIndex(), 3u);
|
||||
EXPECT_EQ(navigation.GetSelectionAnchorIndex(), 3u);
|
||||
|
||||
EXPECT_FALSE(navigation.SetCurrentIndex(3u, false));
|
||||
EXPECT_TRUE(navigation.SetSelectionAnchorIndex(2u));
|
||||
EXPECT_TRUE(navigation.SetItemCount(2u));
|
||||
EXPECT_EQ(navigation.GetCurrentIndex(), 1u);
|
||||
EXPECT_EQ(navigation.GetSelectionAnchorIndex(), 1u);
|
||||
|
||||
EXPECT_TRUE(navigation.SetItemCount(0u));
|
||||
EXPECT_FALSE(navigation.HasCurrentIndex());
|
||||
EXPECT_EQ(navigation.GetCurrentIndex(), UIKeyboardNavigationModel::InvalidIndex);
|
||||
EXPECT_FALSE(navigation.HasSelectionAnchor());
|
||||
EXPECT_EQ(navigation.GetSelectionAnchorIndex(), UIKeyboardNavigationModel::InvalidIndex);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
80
tests/Core/UI/test_ui_property_edit_model.cpp
Normal file
80
tests/Core/UI/test_ui_property_edit_model.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEngine/UI/Widgets/UIPropertyEditModel.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::UI::Widgets::UIPropertyEditModel;
|
||||
|
||||
TEST(UIPropertyEditModelTest, BeginEditTracksActiveFieldAndInitialValue) {
|
||||
UIPropertyEditModel model = {};
|
||||
|
||||
EXPECT_FALSE(model.HasActiveEdit());
|
||||
EXPECT_TRUE(model.GetActiveFieldId().empty());
|
||||
EXPECT_TRUE(model.GetStagedValue().empty());
|
||||
EXPECT_FALSE(model.IsDirty());
|
||||
|
||||
EXPECT_FALSE(model.BeginEdit("", "12.0"));
|
||||
EXPECT_TRUE(model.BeginEdit("transform.position.x", "12.0"));
|
||||
EXPECT_TRUE(model.HasActiveEdit());
|
||||
EXPECT_EQ(model.GetActiveFieldId(), "transform.position.x");
|
||||
EXPECT_EQ(model.GetStagedValue(), "12.0");
|
||||
EXPECT_FALSE(model.IsDirty());
|
||||
|
||||
EXPECT_FALSE(model.BeginEdit("transform.position.x", "12.0"));
|
||||
}
|
||||
|
||||
TEST(UIPropertyEditModelTest, UpdateStagedValueTracksDirtyAgainstBaseline) {
|
||||
UIPropertyEditModel model = {};
|
||||
|
||||
EXPECT_FALSE(model.UpdateStagedValue("3.5"));
|
||||
ASSERT_TRUE(model.BeginEdit("light.intensity", "1.0"));
|
||||
|
||||
EXPECT_TRUE(model.UpdateStagedValue("3.5"));
|
||||
EXPECT_EQ(model.GetStagedValue(), "3.5");
|
||||
EXPECT_TRUE(model.IsDirty());
|
||||
|
||||
EXPECT_FALSE(model.UpdateStagedValue("3.5"));
|
||||
EXPECT_TRUE(model.UpdateStagedValue("1.0"));
|
||||
EXPECT_EQ(model.GetStagedValue(), "1.0");
|
||||
EXPECT_FALSE(model.IsDirty());
|
||||
}
|
||||
|
||||
TEST(UIPropertyEditModelTest, CommitEditReturnsPayloadAndClearsState) {
|
||||
UIPropertyEditModel model = {};
|
||||
ASSERT_TRUE(model.BeginEdit("material.albedo", "#ffffff"));
|
||||
ASSERT_TRUE(model.UpdateStagedValue("#ffcc00"));
|
||||
|
||||
std::string committedFieldId = {};
|
||||
std::string committedValue = {};
|
||||
EXPECT_TRUE(model.CommitEdit(&committedFieldId, &committedValue));
|
||||
EXPECT_EQ(committedFieldId, "material.albedo");
|
||||
EXPECT_EQ(committedValue, "#ffcc00");
|
||||
|
||||
EXPECT_FALSE(model.HasActiveEdit());
|
||||
EXPECT_TRUE(model.GetActiveFieldId().empty());
|
||||
EXPECT_TRUE(model.GetStagedValue().empty());
|
||||
EXPECT_FALSE(model.IsDirty());
|
||||
EXPECT_FALSE(model.CommitEdit(&committedFieldId, &committedValue));
|
||||
}
|
||||
|
||||
TEST(UIPropertyEditModelTest, CancelEditDropsStagedChangesAndResetsSession) {
|
||||
UIPropertyEditModel model = {};
|
||||
ASSERT_TRUE(model.BeginEdit("camera.fov", "60"));
|
||||
ASSERT_TRUE(model.UpdateStagedValue("75"));
|
||||
ASSERT_TRUE(model.IsDirty());
|
||||
|
||||
EXPECT_TRUE(model.CancelEdit());
|
||||
EXPECT_FALSE(model.HasActiveEdit());
|
||||
EXPECT_TRUE(model.GetActiveFieldId().empty());
|
||||
EXPECT_TRUE(model.GetStagedValue().empty());
|
||||
EXPECT_FALSE(model.IsDirty());
|
||||
EXPECT_FALSE(model.CancelEdit());
|
||||
|
||||
EXPECT_TRUE(model.BeginEdit("camera.nearClip", "0.3"));
|
||||
EXPECT_EQ(model.GetActiveFieldId(), "camera.nearClip");
|
||||
EXPECT_EQ(model.GetStagedValue(), "0.3");
|
||||
EXPECT_FALSE(model.IsDirty());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user