Add shell definition contract

This commit is contained in:
2026-04-07 12:09:26 +08:00
parent 3def94d0e0
commit fb8ef25ff3
4 changed files with 226 additions and 29 deletions

View File

@@ -24,12 +24,17 @@ using XCEngine::UI::Editor::UIEditorCommandDispatchStatus;
using XCEngine::UI::Editor::UIEditorCommandDispatcher;
using XCEngine::UI::Editor::UIEditorCommandPanelSource;
using XCEngine::UI::Editor::UIEditorCommandRegistry;
using XCEngine::UI::Editor::UIEditorMenuCheckedStateSource;
using XCEngine::UI::Editor::UIEditorMenuItemKind;
using XCEngine::UI::Editor::UIEditorMenuDescriptor;
using XCEngine::UI::Editor::UIEditorMenuItemDescriptor;
using XCEngine::UI::Editor::UIEditorMenuModel;
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::UIEditorShellInteractionDefinition;
using XCEngine::UI::Editor::UIEditorShellInteractionFrame;
using XCEngine::UI::Editor::UIEditorShellInteractionMenuButtonRequest;
using XCEngine::UI::Editor::UIEditorShellInteractionModel;
@@ -185,6 +190,31 @@ UIEditorShellInteractionModel BuildInteractionModel() {
return model;
}
UIEditorShellInteractionDefinition BuildInteractionDefinition() {
UIEditorMenuItemDescriptor focusInspector = {};
focusInspector.kind = UIEditorMenuItemKind::Command;
focusInspector.itemId = "window-focus-inspector";
focusInspector.label = "Focus Inspector";
focusInspector.commandId = "workspace.focus_inspector";
focusInspector.checkedState = {
UIEditorMenuCheckedStateSource::PanelActive,
"inspector"
};
UIEditorMenuDescriptor windowMenu = {};
windowMenu.menuId = "window";
windowMenu.label = "Window";
windowMenu.items = { focusInspector };
UIEditorShellInteractionDefinition definition = {};
definition.menuModel.menus = { windowMenu };
definition.statusSegments = {
{ "mode", "Shell Contract", UIEditorStatusBarSlot::Leading, {}, true, true, 78.0f }
};
definition.workspacePresentations = BuildInteractionModel().workspacePresentations;
return definition;
}
UIEditorWorkspaceController BuildController() {
return BuildDefaultUIEditorWorkspaceController(BuildPanelRegistry(), BuildWorkspace());
}
@@ -426,6 +456,59 @@ TEST(UIEditorShellInteractionTest, ClickCommandDispatchesInsideShellAndUpdatesWo
EXPECT_TRUE(frame.request.popupRequests.empty());
}
TEST(UIEditorShellInteractionTest, DefinitionContractRefreshesResolvedMenuAfterCommandDispatch) {
auto controller = BuildController();
const UIEditorShellInteractionDefinition definition = BuildInteractionDefinition();
const UIEditorCommandDispatcher dispatcher(BuildCommandRegistry());
UIEditorShellInteractionServices services = {};
services.commandDispatcher = &dispatcher;
UIEditorShellInteractionState state = {};
auto frame = UpdateUIEditorShellInteraction(
state,
controller,
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
definition,
{},
services);
ASSERT_EQ(frame.model.resolvedMenuModel.menus.size(), 1u);
ASSERT_EQ(frame.model.resolvedMenuModel.menus.front().items.size(), 1u);
EXPECT_FALSE(frame.model.resolvedMenuModel.menus.front().items.front().checked);
const auto request = ResolveUIEditorShellInteractionRequest(
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
controller,
definition,
state,
{},
services);
ASSERT_EQ(request.menuButtons.size(), 1u);
frame = UpdateUIEditorShellInteraction(
state,
controller,
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
definition,
{ MakeLeftPointerDown(RectCenter(request.menuButtons.front().rect)) },
services);
const auto* commandItem = FindPopupItem(frame, "window-focus-inspector");
ASSERT_NE(commandItem, nullptr);
frame = UpdateUIEditorShellInteraction(
state,
controller,
UIRect(0.0f, 0.0f, 1280.0f, 720.0f),
definition,
{ MakeLeftPointerDown(RectCenter(commandItem->rect)) },
services);
EXPECT_TRUE(frame.result.commandDispatched);
EXPECT_EQ(controller.GetWorkspace().activePanelId, "inspector");
ASSERT_EQ(frame.model.resolvedMenuModel.menus.size(), 1u);
ASSERT_EQ(frame.model.resolvedMenuModel.menus.front().items.size(), 1u);
EXPECT_TRUE(frame.model.resolvedMenuModel.menus.front().items.front().checked);
}
TEST(UIEditorShellInteractionTest, PointerDownOutsideDismissesWholeMenuChain) {
auto controller = BuildController();
const auto model = BuildInteractionModel();