Unify editor shell asset contracts
This commit is contained in:
@@ -42,8 +42,7 @@ struct StructuredEditorShellBinding {
|
||||
|
||||
inline UIEditorShortcutManager BuildStructuredEditorShortcutManager(
|
||||
const EditorShellAsset& asset) {
|
||||
(void)asset;
|
||||
return UIEditorShortcutManager(UIEditorCommandRegistry{});
|
||||
return BuildEditorShellShortcutManager(asset);
|
||||
}
|
||||
|
||||
inline StructuredEditorShellBinding BuildStructuredEditorShellBinding(
|
||||
|
||||
@@ -148,6 +148,14 @@ EditorShellAsset BuildDefaultEditorShellAsset(const std::filesystem::path& repoR
|
||||
return asset;
|
||||
}
|
||||
|
||||
UIEditorShortcutManager BuildEditorShellShortcutManager(const EditorShellAsset& asset) {
|
||||
UIEditorShortcutManager manager(asset.shortcutAsset.commandRegistry);
|
||||
for (const XCEngine::UI::UIShortcutBinding& binding : asset.shortcutAsset.bindings) {
|
||||
manager.RegisterBinding(binding);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
EditorShellAssetValidationResult ValidateEditorShellAsset(const EditorShellAsset& asset) {
|
||||
const UIEditorPanelRegistryValidationResult registryValidation =
|
||||
ValidateUIEditorPanelRegistry(asset.panelRegistry);
|
||||
@@ -188,6 +196,26 @@ EditorShellAssetValidationResult ValidateEditorShellAsset(const EditorShellAsset
|
||||
return shellDefinitionValidation;
|
||||
}
|
||||
|
||||
const UIEditorMenuModelValidationResult shellMenuValidation =
|
||||
ValidateUIEditorMenuModel(
|
||||
asset.shellDefinition.menuModel,
|
||||
asset.shortcutAsset.commandRegistry);
|
||||
if (!shellMenuValidation.IsValid()) {
|
||||
return MakeValidationError(
|
||||
EditorShellAssetValidationCode::InvalidShellMenuModel,
|
||||
shellMenuValidation.message);
|
||||
}
|
||||
|
||||
const UIEditorShortcutManager shortcutManager =
|
||||
BuildEditorShellShortcutManager(asset);
|
||||
const UIEditorShortcutManagerValidationResult shortcutValidation =
|
||||
shortcutManager.ValidateConfiguration();
|
||||
if (!shortcutValidation.IsValid()) {
|
||||
return MakeValidationError(
|
||||
EditorShellAssetValidationCode::InvalidShortcutConfiguration,
|
||||
shortcutValidation.message);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEditor/Core/UIEditorShortcutManager.h>
|
||||
#include <XCEditor/Core/UIEditorShellInteraction.h>
|
||||
#include <XCEditor/Core/UIEditorPanelRegistry.h>
|
||||
#include <XCEditor/Core/UIEditorWorkspaceModel.h>
|
||||
@@ -8,9 +9,15 @@
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine::UI::Editor {
|
||||
|
||||
struct EditorShellShortcutAsset {
|
||||
UIEditorCommandRegistry commandRegistry = {};
|
||||
std::vector<XCEngine::UI::UIShortcutBinding> bindings = {};
|
||||
};
|
||||
|
||||
struct EditorShellAsset {
|
||||
std::string screenId = "editor.shell";
|
||||
std::filesystem::path documentPath = {};
|
||||
@@ -20,6 +27,7 @@ struct EditorShellAsset {
|
||||
UIEditorWorkspaceModel workspace = {};
|
||||
UIEditorWorkspaceSession workspaceSession = {};
|
||||
UIEditorShellInteractionDefinition shellDefinition = {};
|
||||
EditorShellShortcutAsset shortcutAsset = {};
|
||||
};
|
||||
|
||||
enum class EditorShellAssetValidationCode : std::uint8_t {
|
||||
@@ -27,6 +35,8 @@ enum class EditorShellAssetValidationCode : std::uint8_t {
|
||||
InvalidPanelRegistry,
|
||||
InvalidWorkspace,
|
||||
InvalidWorkspaceSession,
|
||||
InvalidShellMenuModel,
|
||||
InvalidShortcutConfiguration,
|
||||
MissingPanelDescriptor,
|
||||
PanelTitleMismatch,
|
||||
PanelPlaceholderMismatch,
|
||||
@@ -46,6 +56,7 @@ struct EditorShellAssetValidationResult {
|
||||
};
|
||||
|
||||
EditorShellAsset BuildDefaultEditorShellAsset(const std::filesystem::path& repoRoot);
|
||||
UIEditorShortcutManager BuildEditorShellShortcutManager(const EditorShellAsset& asset);
|
||||
EditorShellAssetValidationResult ValidateEditorShellAsset(const EditorShellAsset& asset);
|
||||
|
||||
} // namespace XCEngine::UI::Editor
|
||||
|
||||
@@ -4,12 +4,31 @@
|
||||
|
||||
#include <XCEditor/Core/UIEditorPanelRegistry.h>
|
||||
|
||||
#include <XCEngine/Input/InputTypes.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::Input::KeyCode;
|
||||
using XCEngine::UI::Editor::BuildDefaultEditorShellAsset;
|
||||
using XCEngine::UI::Editor::EditorShellAssetValidationCode;
|
||||
using XCEngine::UI::Editor::FindUIEditorPanelDescriptor;
|
||||
using XCEngine::UI::Editor::UIEditorCommandPanelSource;
|
||||
using XCEngine::UI::Editor::UIEditorMenuItemKind;
|
||||
using XCEngine::UI::Editor::UIEditorWorkspaceCommandKind;
|
||||
using XCEngine::UI::Editor::ValidateEditorShellAsset;
|
||||
using XCEngine::UI::UIInputEventType;
|
||||
using XCEngine::UI::UIShortcutBinding;
|
||||
using XCEngine::UI::UIShortcutScope;
|
||||
|
||||
UIShortcutBinding MakeBinding(std::string commandId, KeyCode keyCode) {
|
||||
UIShortcutBinding binding = {};
|
||||
binding.commandId = std::move(commandId);
|
||||
binding.scope = UIShortcutScope::Global;
|
||||
binding.triggerEventType = UIInputEventType::KeyDown;
|
||||
binding.chord.keyCode = static_cast<std::int32_t>(keyCode);
|
||||
binding.chord.modifiers.control = true;
|
||||
return binding;
|
||||
}
|
||||
|
||||
TEST(EditorShellAssetValidationTest, DefaultShellAssetPassesValidation) {
|
||||
const auto shellAsset = BuildDefaultEditorShellAsset(".");
|
||||
@@ -99,6 +118,50 @@ TEST(EditorShellAssetValidationTest, ValidationRejectsMissingRequiredShellPresen
|
||||
EditorShellAssetValidationCode::MissingRequiredShellPresentation);
|
||||
}
|
||||
|
||||
TEST(EditorShellAssetValidationTest, ValidationRejectsInvalidShellMenuModel) {
|
||||
auto shellAsset = BuildDefaultEditorShellAsset(".");
|
||||
shellAsset.shellDefinition.menuModel.menus = {
|
||||
{
|
||||
"window",
|
||||
"Window",
|
||||
{
|
||||
{
|
||||
UIEditorMenuItemKind::Command,
|
||||
"reset-layout",
|
||||
{},
|
||||
"workspace.reset_layout",
|
||||
{},
|
||||
{}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const auto validation = ValidateEditorShellAsset(shellAsset);
|
||||
EXPECT_EQ(
|
||||
validation.code,
|
||||
EditorShellAssetValidationCode::InvalidShellMenuModel);
|
||||
}
|
||||
|
||||
TEST(EditorShellAssetValidationTest, ValidationRejectsInvalidShortcutConfiguration) {
|
||||
auto shellAsset = BuildDefaultEditorShellAsset(".");
|
||||
shellAsset.shortcutAsset.commandRegistry.commands = {
|
||||
{
|
||||
"workspace.reset_layout",
|
||||
"Reset Layout",
|
||||
{ UIEditorWorkspaceCommandKind::ResetWorkspace, UIEditorCommandPanelSource::None, {} }
|
||||
}
|
||||
};
|
||||
shellAsset.shortcutAsset.bindings = {
|
||||
MakeBinding("missing.command", KeyCode::R)
|
||||
};
|
||||
|
||||
const auto validation = ValidateEditorShellAsset(shellAsset);
|
||||
EXPECT_EQ(
|
||||
validation.code,
|
||||
EditorShellAssetValidationCode::InvalidShortcutConfiguration);
|
||||
}
|
||||
|
||||
TEST(EditorShellAssetValidationTest, ValidationRejectsShellPresentationKindMismatch) {
|
||||
auto shellAsset = BuildDefaultEditorShellAsset(".");
|
||||
ASSERT_EQ(
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <XCEditor/Core/UIEditorShellInteraction.h>
|
||||
#include <XCEditor/Core/UIEditorWorkspaceModel.h>
|
||||
#include <XCEditor/Core/UIEditorWorkspaceSession.h>
|
||||
#include <XCEngine/Input/InputTypes.h>
|
||||
#include <XCEngine/UI/Runtime/UIScreenDocumentHost.h>
|
||||
#include <XCEngine/UI/Runtime/UIScreenPlayer.h>
|
||||
|
||||
@@ -18,15 +19,22 @@
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::Input::KeyCode;
|
||||
using XCEngine::UI::Editor::BuildDefaultEditorShellAsset;
|
||||
using XCEngine::UI::Editor::BuildStructuredEditorShellBinding;
|
||||
using XCEngine::UI::Editor::BuildStructuredEditorShellServices;
|
||||
using XCEngine::UI::Editor::ResolveUIEditorShellInteractionModel;
|
||||
using XCEngine::UI::Editor::AreUIEditorWorkspaceModelsEquivalent;
|
||||
using XCEngine::UI::Editor::AreUIEditorWorkspaceSessionsEquivalent;
|
||||
using XCEngine::UI::Editor::UIEditorCommandPanelSource;
|
||||
using XCEngine::UI::Editor::UIEditorMenuItemKind;
|
||||
using XCEngine::UI::Editor::UIEditorWorkspaceCommandKind;
|
||||
using XCEngine::UI::UIDrawCommand;
|
||||
using XCEngine::UI::UIDrawCommandType;
|
||||
using XCEngine::UI::UIDrawData;
|
||||
using XCEngine::UI::UIInputEventType;
|
||||
using XCEngine::UI::UIShortcutBinding;
|
||||
using XCEngine::UI::UIShortcutScope;
|
||||
using XCEngine::UI::Runtime::UIScreenAsset;
|
||||
using XCEngine::UI::Runtime::UIScreenFrameInput;
|
||||
using XCEngine::UI::Runtime::UIScreenPlayer;
|
||||
@@ -137,6 +145,16 @@ bool ShellDefinitionsMatch(
|
||||
return true;
|
||||
}
|
||||
|
||||
UIShortcutBinding MakeBinding(std::string commandId, KeyCode keyCode) {
|
||||
UIShortcutBinding binding = {};
|
||||
binding.commandId = std::move(commandId);
|
||||
binding.scope = UIShortcutScope::Global;
|
||||
binding.triggerEventType = UIInputEventType::KeyDown;
|
||||
binding.chord.keyCode = static_cast<std::int32_t>(keyCode);
|
||||
binding.chord.modifiers.control = true;
|
||||
return binding;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(EditorUIStructuredShellTest, AuthoredEditorShellLoadsFromRepositoryResources) {
|
||||
@@ -173,9 +191,24 @@ TEST(EditorUIStructuredShellTest, AuthoredEditorShellLoadsFromRepositoryResource
|
||||
TEST(EditorUIStructuredShellTest, StructuredShellBindingUsesEditorShellAssetAsSingleSource) {
|
||||
auto shell = BuildDefaultEditorShellAsset(RepoRootPath());
|
||||
shell.shellDefinition.statusSegments.front().label = "Asset Contract";
|
||||
shell.shortcutAsset.commandRegistry.commands = {
|
||||
{
|
||||
"workspace.reset_layout",
|
||||
"Reset Layout",
|
||||
{ UIEditorWorkspaceCommandKind::ResetWorkspace, UIEditorCommandPanelSource::None, {} }
|
||||
}
|
||||
};
|
||||
shell.shortcutAsset.bindings = {
|
||||
MakeBinding("workspace.reset_layout", KeyCode::R)
|
||||
};
|
||||
XCEngine::UI::Editor::UIEditorMenuItemDescriptor assetCommand = {};
|
||||
assetCommand.kind = UIEditorMenuItemKind::Command;
|
||||
assetCommand.itemId = "asset-reset-layout";
|
||||
assetCommand.commandId = "workspace.reset_layout";
|
||||
XCEngine::UI::Editor::UIEditorMenuDescriptor assetMenu = {};
|
||||
assetMenu.menuId = "asset";
|
||||
assetMenu.label = "Asset";
|
||||
assetMenu.items = { assetCommand };
|
||||
shell.shellDefinition.menuModel.menus = { assetMenu };
|
||||
const auto binding = BuildStructuredEditorShellBinding(shell);
|
||||
|
||||
@@ -203,6 +236,10 @@ TEST(EditorUIStructuredShellTest, StructuredShellBindingUsesEditorShellAssetAsSi
|
||||
ASSERT_EQ(model.resolvedMenuModel.menus.size(), 1u);
|
||||
EXPECT_EQ(model.resolvedMenuModel.menus.front().menuId, "asset");
|
||||
EXPECT_EQ(model.resolvedMenuModel.menus.front().label, "Asset");
|
||||
ASSERT_EQ(model.resolvedMenuModel.menus.front().items.size(), 1u);
|
||||
EXPECT_EQ(model.resolvedMenuModel.menus.front().items.front().commandId, "workspace.reset_layout");
|
||||
EXPECT_EQ(model.resolvedMenuModel.menus.front().items.front().label, "Reset Layout");
|
||||
EXPECT_EQ(model.resolvedMenuModel.menus.front().items.front().shortcutText, "Ctrl+R");
|
||||
ASSERT_EQ(model.statusSegments.size(), shell.shellDefinition.statusSegments.size());
|
||||
EXPECT_EQ(model.statusSegments.front().label, shell.shellDefinition.statusSegments.front().label);
|
||||
ASSERT_EQ(
|
||||
|
||||
Reference in New Issue
Block a user