Add editor shell interaction contract
This commit is contained in:
@@ -10,6 +10,7 @@ set(EDITOR_UI_UNIT_TEST_SOURCES
|
||||
test_ui_editor_menu_popup.cpp
|
||||
test_ui_editor_panel_registry.cpp
|
||||
test_ui_editor_shell_compose.cpp
|
||||
test_ui_editor_shell_interaction.cpp
|
||||
test_ui_editor_collection_primitives.cpp
|
||||
test_ui_editor_dock_host.cpp
|
||||
test_ui_editor_panel_chrome.cpp
|
||||
|
||||
545
tests/UI/Editor/unit/test_ui_editor_shell_interaction.cpp
Normal file
545
tests/UI/Editor/unit/test_ui_editor_shell_interaction.cpp
Normal file
@@ -0,0 +1,545 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEditor/Core/UIEditorShellInteraction.h>
|
||||
#include <XCEditor/Core/UIEditorWorkspaceModel.h>
|
||||
#include <XCEditor/Core/UIEditorWorkspaceSession.h>
|
||||
|
||||
#include <XCEngine/Input/InputTypes.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::Input::KeyCode;
|
||||
using XCEngine::UI::UIInputEvent;
|
||||
using XCEngine::UI::UIInputEventType;
|
||||
using XCEngine::UI::UIPoint;
|
||||
using XCEngine::UI::UIRect;
|
||||
using XCEngine::UI::UIPointerButton;
|
||||
using XCEngine::UI::Editor::BuildDefaultUIEditorWorkspaceSession;
|
||||
using XCEngine::UI::Editor::BuildUIEditorWorkspacePanel;
|
||||
using XCEngine::UI::Editor::BuildUIEditorWorkspaceSplit;
|
||||
using XCEngine::UI::Editor::BuildUIEditorWorkspaceTabStack;
|
||||
using XCEngine::UI::Editor::ResolveUIEditorShellInteractionRequest;
|
||||
using XCEngine::UI::Editor::UIEditorMenuItemKind;
|
||||
using XCEngine::UI::Editor::UIEditorPanelPresentationKind;
|
||||
using XCEngine::UI::Editor::UIEditorPanelRegistry;
|
||||
using XCEngine::UI::Editor::UIEditorResolvedMenuDescriptor;
|
||||
using XCEngine::UI::Editor::UIEditorResolvedMenuItem;
|
||||
using XCEngine::UI::Editor::UIEditorResolvedMenuModel;
|
||||
using XCEngine::UI::Editor::UIEditorShellInteractionFrame;
|
||||
using XCEngine::UI::Editor::UIEditorShellInteractionMenuButtonRequest;
|
||||
using XCEngine::UI::Editor::UIEditorShellInteractionModel;
|
||||
using XCEngine::UI::Editor::UIEditorShellInteractionPopupItemRequest;
|
||||
using XCEngine::UI::Editor::UIEditorShellInteractionState;
|
||||
using XCEngine::UI::Editor::UIEditorWorkspaceModel;
|
||||
using XCEngine::UI::Editor::UIEditorWorkspacePanelPresentationModel;
|
||||
using XCEngine::UI::Editor::UIEditorWorkspaceSplitAxis;
|
||||
using XCEngine::UI::Editor::UpdateUIEditorShellInteraction;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorMenuPopupInvalidIndex;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorStatusBarSlot;
|
||||
using XCEngine::UI::Widgets::UIPopupDismissReason;
|
||||
|
||||
UIEditorPanelRegistry BuildPanelRegistry() {
|
||||
UIEditorPanelRegistry registry = {};
|
||||
registry.panels = {
|
||||
{ "hierarchy", "Hierarchy", UIEditorPanelPresentationKind::Placeholder, true, true, false },
|
||||
{ "scene", "Scene", UIEditorPanelPresentationKind::ViewportShell, false, true, false },
|
||||
{ "inspector", "Inspector", UIEditorPanelPresentationKind::Placeholder, true, true, true }
|
||||
};
|
||||
return registry;
|
||||
}
|
||||
|
||||
UIEditorWorkspaceModel BuildWorkspace() {
|
||||
UIEditorWorkspaceModel workspace = {};
|
||||
workspace.root = BuildUIEditorWorkspaceSplit(
|
||||
"root",
|
||||
UIEditorWorkspaceSplitAxis::Horizontal,
|
||||
0.28f,
|
||||
BuildUIEditorWorkspacePanel("hierarchy-node", "hierarchy", "Hierarchy", true),
|
||||
BuildUIEditorWorkspaceSplit(
|
||||
"main",
|
||||
UIEditorWorkspaceSplitAxis::Horizontal,
|
||||
0.72f,
|
||||
BuildUIEditorWorkspacePanel("scene-node", "scene", "Scene"),
|
||||
BuildUIEditorWorkspacePanel("inspector-node", "inspector", "Inspector", true)));
|
||||
workspace.activePanelId = "scene";
|
||||
return workspace;
|
||||
}
|
||||
|
||||
UIEditorResolvedMenuModel BuildResolvedMenuModel() {
|
||||
UIEditorResolvedMenuModel model = {};
|
||||
|
||||
UIEditorResolvedMenuItem fileWorkspaceTools = {};
|
||||
fileWorkspaceTools.kind = UIEditorMenuItemKind::Submenu;
|
||||
fileWorkspaceTools.itemId = "file-workspace-tools";
|
||||
fileWorkspaceTools.label = "Workspace Tools";
|
||||
fileWorkspaceTools.enabled = true;
|
||||
fileWorkspaceTools.children = {
|
||||
UIEditorResolvedMenuItem{
|
||||
UIEditorMenuItemKind::Command,
|
||||
"file-show-inspector",
|
||||
"Show Inspector",
|
||||
"workspace.show_inspector",
|
||||
"Show Inspector",
|
||||
"Ctrl+I",
|
||||
true,
|
||||
false
|
||||
},
|
||||
UIEditorResolvedMenuItem{
|
||||
UIEditorMenuItemKind::Command,
|
||||
"file-reset-layout",
|
||||
"Reset Layout",
|
||||
"workspace.reset_layout",
|
||||
"Reset Layout",
|
||||
"Ctrl+R",
|
||||
true,
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
UIEditorResolvedMenuDescriptor fileMenu = {};
|
||||
fileMenu.menuId = "file";
|
||||
fileMenu.label = "File";
|
||||
fileMenu.items = {
|
||||
fileWorkspaceTools,
|
||||
UIEditorResolvedMenuItem{
|
||||
UIEditorMenuItemKind::Command,
|
||||
"file-close",
|
||||
"Close",
|
||||
"workspace.close",
|
||||
"Close",
|
||||
"Ctrl+W",
|
||||
true,
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
UIEditorResolvedMenuDescriptor windowMenu = {};
|
||||
windowMenu.menuId = "window";
|
||||
windowMenu.label = "Window";
|
||||
windowMenu.items = {
|
||||
UIEditorResolvedMenuItem{
|
||||
UIEditorMenuItemKind::Command,
|
||||
"window-focus-inspector",
|
||||
"Focus Inspector",
|
||||
"workspace.focus_inspector",
|
||||
"Focus Inspector",
|
||||
"Ctrl+P",
|
||||
true,
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
model.menus = { fileMenu, windowMenu };
|
||||
return model;
|
||||
}
|
||||
|
||||
UIEditorShellInteractionModel BuildInteractionModel() {
|
||||
UIEditorShellInteractionModel model = {};
|
||||
model.resolvedMenuModel = BuildResolvedMenuModel();
|
||||
model.statusSegments = {
|
||||
{ "mode", "Scene", UIEditorStatusBarSlot::Leading, {}, true, true, 78.0f }
|
||||
};
|
||||
|
||||
UIEditorWorkspacePanelPresentationModel presentation = {};
|
||||
presentation.panelId = "scene";
|
||||
presentation.kind = UIEditorPanelPresentationKind::ViewportShell;
|
||||
presentation.viewportShellModel.spec.chrome.title = "Scene";
|
||||
presentation.viewportShellModel.frame.statusText = "Viewport";
|
||||
model.workspacePresentations = { presentation };
|
||||
return model;
|
||||
}
|
||||
|
||||
const UIEditorShellInteractionMenuButtonRequest* FindMenuButton(
|
||||
const UIEditorShellInteractionFrame& frame,
|
||||
std::string_view menuId) {
|
||||
for (const auto& button : frame.request.menuButtons) {
|
||||
if (button.menuId == menuId) {
|
||||
return &button;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const UIEditorShellInteractionPopupItemRequest* FindPopupItem(
|
||||
const UIEditorShellInteractionFrame& frame,
|
||||
std::string_view itemId) {
|
||||
for (const auto& popup : frame.request.popupRequests) {
|
||||
for (const auto& item : popup.itemRequests) {
|
||||
if (item.itemId == itemId) {
|
||||
return &item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UIPoint RectCenter(const UIRect& rect) {
|
||||
return UIPoint(rect.x + rect.width * 0.5f, rect.y + rect.height * 0.5f);
|
||||
}
|
||||
|
||||
UIInputEvent MakePointerMove(const UIPoint& position) {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::PointerMove;
|
||||
event.position = position;
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakeLeftPointerDown(const UIPoint& position) {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::PointerButtonDown;
|
||||
event.position = position;
|
||||
event.pointerButton = UIPointerButton::Left;
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakeKeyDown(KeyCode keyCode) {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::KeyDown;
|
||||
event.keyCode = static_cast<std::int32_t>(keyCode);
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakeFocusLost() {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::FocusLost;
|
||||
return event;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(UIEditorShellInteractionTest, ClickMenuBarRootOpensSingleRootPopup) {
|
||||
const auto registry = BuildPanelRegistry();
|
||||
const auto workspace = BuildWorkspace();
|
||||
const auto session = BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
const auto model = BuildInteractionModel();
|
||||
|
||||
UIEditorShellInteractionState state = {};
|
||||
const auto request = ResolveUIEditorShellInteractionRequest(
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{},
|
||||
state);
|
||||
ASSERT_EQ(request.menuButtons.size(), 2u);
|
||||
|
||||
const auto frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeLeftPointerDown(RectCenter(request.menuButtons.front().rect)) });
|
||||
|
||||
EXPECT_TRUE(state.menuSession.HasOpenMenu());
|
||||
EXPECT_EQ(frame.openRootMenuId, "file");
|
||||
ASSERT_EQ(frame.request.popupRequests.size(), 1u);
|
||||
EXPECT_EQ(frame.request.popupRequests.front().menuId, "file");
|
||||
EXPECT_EQ(state.composeState.menuBarState.openIndex, 0u);
|
||||
}
|
||||
|
||||
TEST(UIEditorShellInteractionTest, HoverOtherRootSwitchesRootPopup) {
|
||||
const auto registry = BuildPanelRegistry();
|
||||
const auto workspace = BuildWorkspace();
|
||||
const auto session = BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
const auto model = BuildInteractionModel();
|
||||
|
||||
UIEditorShellInteractionState state = {};
|
||||
auto frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeLeftPointerDown(UIPoint(40.0f, 30.0f)) });
|
||||
const auto* windowButton = FindMenuButton(frame, "window");
|
||||
ASSERT_NE(windowButton, nullptr);
|
||||
|
||||
frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakePointerMove(RectCenter(windowButton->rect)) });
|
||||
|
||||
EXPECT_TRUE(state.menuSession.IsMenuOpen("window"));
|
||||
EXPECT_EQ(frame.openRootMenuId, "window");
|
||||
ASSERT_EQ(frame.request.popupRequests.size(), 1u);
|
||||
EXPECT_EQ(frame.request.popupRequests.front().menuId, "window");
|
||||
}
|
||||
|
||||
TEST(UIEditorShellInteractionTest, HoverSubmenuOpensChildPopupAndEscapeCollapsesChain) {
|
||||
const auto registry = BuildPanelRegistry();
|
||||
const auto workspace = BuildWorkspace();
|
||||
const auto session = BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
const auto model = BuildInteractionModel();
|
||||
|
||||
UIEditorShellInteractionState state = {};
|
||||
auto frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeLeftPointerDown(UIPoint(40.0f, 30.0f)) });
|
||||
const auto* submenuItem = FindPopupItem(frame, "file-workspace-tools");
|
||||
ASSERT_NE(submenuItem, nullptr);
|
||||
ASSERT_TRUE(submenuItem->hasSubmenu);
|
||||
|
||||
frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakePointerMove(RectCenter(submenuItem->rect)) });
|
||||
|
||||
ASSERT_EQ(frame.request.popupRequests.size(), 2u);
|
||||
EXPECT_EQ(frame.request.popupRequests[1].sourceItemId, "file-workspace-tools");
|
||||
EXPECT_NE(frame.popupFrames.front().popupState.submenuOpenIndex, UIEditorMenuPopupInvalidIndex);
|
||||
|
||||
frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeKeyDown(KeyCode::Escape) });
|
||||
EXPECT_EQ(frame.openRootMenuId, "file");
|
||||
ASSERT_EQ(frame.request.popupRequests.size(), 1u);
|
||||
|
||||
frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeKeyDown(KeyCode::Escape) });
|
||||
EXPECT_FALSE(state.menuSession.HasOpenMenu());
|
||||
EXPECT_TRUE(frame.request.popupRequests.empty());
|
||||
}
|
||||
|
||||
TEST(UIEditorShellInteractionTest, ClickCommandReturnsDispatchHookAndClosesMenu) {
|
||||
const auto registry = BuildPanelRegistry();
|
||||
const auto workspace = BuildWorkspace();
|
||||
const auto session = BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
const auto model = BuildInteractionModel();
|
||||
|
||||
UIEditorShellInteractionState state = {};
|
||||
auto frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeLeftPointerDown(UIPoint(40.0f, 30.0f)) });
|
||||
const auto* commandItem = FindPopupItem(frame, "file-close");
|
||||
ASSERT_NE(commandItem, nullptr);
|
||||
|
||||
frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeLeftPointerDown(RectCenter(commandItem->rect)) });
|
||||
|
||||
EXPECT_TRUE(frame.result.commandTriggered);
|
||||
EXPECT_EQ(frame.result.commandId, "workspace.close");
|
||||
EXPECT_FALSE(state.menuSession.HasOpenMenu());
|
||||
EXPECT_TRUE(frame.request.popupRequests.empty());
|
||||
}
|
||||
|
||||
TEST(UIEditorShellInteractionTest, PointerDownOutsideDismissesWholeMenuChain) {
|
||||
const auto registry = BuildPanelRegistry();
|
||||
const auto workspace = BuildWorkspace();
|
||||
const auto session = BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
const auto model = BuildInteractionModel();
|
||||
|
||||
UIEditorShellInteractionState state = {};
|
||||
auto frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeLeftPointerDown(UIPoint(40.0f, 30.0f)) });
|
||||
ASSERT_TRUE(state.menuSession.HasOpenMenu());
|
||||
|
||||
frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeLeftPointerDown(UIPoint(900.0f, 500.0f)) });
|
||||
|
||||
EXPECT_TRUE(frame.result.consumed);
|
||||
EXPECT_FALSE(state.menuSession.HasOpenMenu());
|
||||
EXPECT_TRUE(frame.request.popupRequests.empty());
|
||||
}
|
||||
|
||||
TEST(UIEditorShellInteractionTest, DisabledSubmenuDoesNotOpenChildPopup) {
|
||||
const auto registry = BuildPanelRegistry();
|
||||
const auto workspace = BuildWorkspace();
|
||||
const auto session = BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
auto model = BuildInteractionModel();
|
||||
model.resolvedMenuModel.menus[0].items[0].enabled = false;
|
||||
|
||||
UIEditorShellInteractionState state = {};
|
||||
auto frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeLeftPointerDown(UIPoint(40.0f, 30.0f)) });
|
||||
const auto* submenuItem = FindPopupItem(frame, "file-workspace-tools");
|
||||
ASSERT_NE(submenuItem, nullptr);
|
||||
ASSERT_TRUE(submenuItem->hasSubmenu);
|
||||
EXPECT_FALSE(submenuItem->enabled);
|
||||
|
||||
frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakePointerMove(RectCenter(submenuItem->rect)) });
|
||||
|
||||
ASSERT_EQ(frame.request.popupRequests.size(), 1u);
|
||||
EXPECT_EQ(frame.request.popupRequests.front().menuId, "file");
|
||||
EXPECT_TRUE(state.menuSession.HasOpenMenu());
|
||||
}
|
||||
|
||||
TEST(UIEditorShellInteractionTest, FocusLostDismissesWholeMenuChain) {
|
||||
const auto registry = BuildPanelRegistry();
|
||||
const auto workspace = BuildWorkspace();
|
||||
const auto session = BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
const auto model = BuildInteractionModel();
|
||||
|
||||
UIEditorShellInteractionState state = {};
|
||||
auto frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeLeftPointerDown(UIPoint(40.0f, 30.0f)) });
|
||||
const auto* submenuItem = FindPopupItem(frame, "file-workspace-tools");
|
||||
ASSERT_NE(submenuItem, nullptr);
|
||||
|
||||
frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakePointerMove(RectCenter(submenuItem->rect)) });
|
||||
ASSERT_EQ(frame.request.popupRequests.size(), 2u);
|
||||
|
||||
frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeFocusLost() });
|
||||
|
||||
EXPECT_TRUE(frame.result.consumed);
|
||||
EXPECT_TRUE(frame.result.menuMutation.changed);
|
||||
EXPECT_EQ(frame.result.menuMutation.dismissReason, UIPopupDismissReason::FocusLoss);
|
||||
EXPECT_FALSE(state.menuSession.HasOpenMenu());
|
||||
EXPECT_TRUE(frame.request.popupRequests.empty());
|
||||
}
|
||||
|
||||
TEST(UIEditorShellInteractionTest, OpenMenuConsumesWorkspacePointerDownForThatFrame) {
|
||||
const auto registry = BuildPanelRegistry();
|
||||
const auto workspace = BuildWorkspace();
|
||||
const auto session = BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
const auto model = BuildInteractionModel();
|
||||
|
||||
UIEditorShellInteractionState state = {};
|
||||
auto frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeLeftPointerDown(UIPoint(40.0f, 30.0f)) });
|
||||
ASSERT_TRUE(state.menuSession.HasOpenMenu());
|
||||
ASSERT_FALSE(frame.shellFrame.workspaceFrame.viewportFrames.empty());
|
||||
|
||||
const UIRect inputRect =
|
||||
frame.shellFrame.workspaceFrame.viewportFrames.front().viewportShellFrame.slotLayout.inputRect;
|
||||
frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeLeftPointerDown(RectCenter(inputRect)) });
|
||||
|
||||
EXPECT_FALSE(frame.shellFrame.workspaceFrame.viewportFrames.front()
|
||||
.viewportShellFrame.inputFrame.pointerPressedInside);
|
||||
EXPECT_FALSE(state.menuSession.HasOpenMenu());
|
||||
}
|
||||
|
||||
TEST(UIEditorShellInteractionTest, InvalidResolvedMenuStateClosesInvisibleModalChain) {
|
||||
const auto registry = BuildPanelRegistry();
|
||||
const auto workspace = BuildWorkspace();
|
||||
const auto session = BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
const auto model = BuildInteractionModel();
|
||||
|
||||
UIEditorShellInteractionState state = {};
|
||||
auto frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
model,
|
||||
{ MakeLeftPointerDown(UIPoint(40.0f, 30.0f)) });
|
||||
ASSERT_TRUE(state.menuSession.HasOpenMenu());
|
||||
ASSERT_EQ(frame.request.popupRequests.size(), 1u);
|
||||
|
||||
auto updatedModel = model;
|
||||
updatedModel.resolvedMenuModel.menus.erase(updatedModel.resolvedMenuModel.menus.begin());
|
||||
|
||||
frame = UpdateUIEditorShellInteraction(
|
||||
state,
|
||||
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
|
||||
registry,
|
||||
workspace,
|
||||
session,
|
||||
updatedModel,
|
||||
{});
|
||||
|
||||
EXPECT_TRUE(frame.result.consumed);
|
||||
EXPECT_TRUE(frame.result.menuMutation.changed);
|
||||
EXPECT_EQ(frame.result.menuMutation.dismissReason, UIPopupDismissReason::Programmatic);
|
||||
EXPECT_FALSE(state.menuSession.HasOpenMenu());
|
||||
EXPECT_TRUE(frame.request.popupRequests.empty());
|
||||
}
|
||||
Reference in New Issue
Block a user