Wire XCUI layout lab panel keyboard navigation
This commit is contained in:
@@ -87,6 +87,7 @@ Current gap:
|
|||||||
- The legacy ImGui hosted-preview presenter now also accepts an explicit draw-target binding object, so presenter-side `ImGui::GetWindowDrawList()` lookup is no longer hard-coded inside the generic presenter path and can stay isolated behind the ImGui adapter layer.
|
- The legacy ImGui hosted-preview presenter now also accepts an explicit draw-target binding object, so presenter-side `ImGui::GetWindowDrawList()` lookup is no longer hard-coded inside the generic presenter path and can stay isolated behind the ImGui adapter layer.
|
||||||
- `Application` shell menu toggles and global shortcuts now route through `XCUIEditorCommandRouter` instead of directly mutating shell booleans from menu callbacks, giving the editor layer a real command-routing seam.
|
- `Application` shell menu toggles and global shortcuts now route through `XCUIEditorCommandRouter` instead of directly mutating shell booleans from menu callbacks, giving the editor layer a real command-routing seam.
|
||||||
- `LayoutLab` runtime now consumes the shared `UIKeyboardNavigationModel` for abstract list/tree/property navigation actions (`previous/next/home/end/collapse/expand`), so keyboard collection traversal rules are no longer trapped in sandbox-local state.
|
- `LayoutLab` runtime now consumes the shared `UIKeyboardNavigationModel` for abstract list/tree/property navigation actions (`previous/next/home/end/collapse/expand`), so keyboard collection traversal rules are no longer trapped in sandbox-local state.
|
||||||
|
- `LayoutLab` panel input now also maps concrete arrow/home/end keys into those shared navigation actions, so keyboard traversal is reachable from the sandbox UI instead of staying runtime-only.
|
||||||
- `XCUIDemoRuntime` now bridges pointer activation, text-edit commands, and shortcut-triggered commands through a unified command path, and `DrainPendingCommandIds()` now preserves mixed pointer/text/shortcut ordering.
|
- `XCUIDemoRuntime` now bridges pointer activation, text-edit commands, and shortcut-triggered commands through a unified command path, and `DrainPendingCommandIds()` now preserves mixed pointer/text/shortcut ordering.
|
||||||
- `new_editor` now also has a pure `XCUIShellChromeState` model covering panel visibility, hosted-preview mode, and shell-level view toggles without depending on ImGui, `Application`, or the old editor.
|
- `new_editor` now also has a pure `XCUIShellChromeState` model covering panel visibility, hosted-preview mode, and shell-level view toggles without depending on ImGui, `Application`, or the old editor.
|
||||||
- `XCNewEditor` builds successfully to `build/new_editor/bin/Debug/XCNewEditor.exe`.
|
- `XCNewEditor` builds successfully to `build/new_editor/bin/Debug/XCNewEditor.exe`.
|
||||||
@@ -96,7 +97,7 @@ Current gap:
|
|||||||
- The shell is still ImGui-hosted.
|
- The shell is still ImGui-hosted.
|
||||||
- Legacy hosted preview still depends on an ImGui-specific inline draw target binding for presentation.
|
- Legacy hosted preview still depends on an ImGui-specific inline draw target binding for presentation.
|
||||||
- The new panel-canvas seam still only has an ImGui adapter today; a native panel/shell host still needs to replace it before ImGui can stop being the default editor host path.
|
- The new panel-canvas seam still only has an ImGui adapter today; a native panel/shell host still needs to replace it before ImGui can stop being the default editor host path.
|
||||||
- Editor-specialized widgets are still incomplete at the shared-module level: the authored prototypes exist, but virtualization, multi-selection/focus traversal, toolbar/menu chrome, and icon-atlas widgets are not yet extracted into reusable XCUI modules, and panel-level keyboard mapping plus shell-state adoption are still only partially integrated.
|
- Editor-specialized widgets are still incomplete at the shared-module level: the authored prototypes exist, but virtualization, multi-selection/focus traversal, toolbar/menu chrome, and icon-atlas widgets are not yet extracted into reusable XCUI modules, and broader editor-host keybinding plus full shell-state adoption are still only partially integrated.
|
||||||
|
|
||||||
## Validated This Phase
|
## Validated This Phase
|
||||||
|
|
||||||
@@ -111,6 +112,7 @@ Current gap:
|
|||||||
- `new_editor_xcui_shell_chrome_state_tests`: `8/8`
|
- `new_editor_xcui_shell_chrome_state_tests`: `8/8`
|
||||||
- `new_editor_xcui_panel_canvas_host_tests`: `2/2`
|
- `new_editor_xcui_panel_canvas_host_tests`: `2/2`
|
||||||
- `new_editor_imgui_xcui_panel_canvas_host_tests`: `1/1`
|
- `new_editor_imgui_xcui_panel_canvas_host_tests`: `1/1`
|
||||||
|
- `new_editor_xcui_layout_lab_panel_tests`: `2/2`
|
||||||
- `XCNewEditor` Debug target builds successfully
|
- `XCNewEditor` Debug target builds successfully
|
||||||
- `core_ui_tests`: `52 total` (`50` passed, `2` skipped because `KeyCode::Delete` currently aliases `Backspace`)
|
- `core_ui_tests`: `52 total` (`50` passed, `2` skipped because `KeyCode::Delete` currently aliases `Backspace`)
|
||||||
- `scene_tests`: `68/68`
|
- `scene_tests`: `68/68`
|
||||||
@@ -214,6 +216,7 @@ Current gap:
|
|||||||
- panel/runtime callers still preserve the same legacy and native-preview behavior
|
- panel/runtime callers still preserve the same legacy and native-preview behavior
|
||||||
- `LayoutLab` now resolves editor collection widget taxonomy and metrics through shared `UIEditorCollectionPrimitives` helpers instead of duplicating the same tag and metric rules inside the sandbox runtime.
|
- `LayoutLab` now resolves editor collection widget taxonomy and metrics through shared `UIEditorCollectionPrimitives` helpers instead of duplicating the same tag and metric rules inside the sandbox runtime.
|
||||||
- `LayoutLab` runtime now consumes shared keyboard-navigation semantics for list/tree/property traversal, while the remaining panel-level key mapping is tracked as an editor-host integration gap rather than a runtime gap.
|
- `LayoutLab` runtime now consumes shared keyboard-navigation semantics for list/tree/property traversal, while the remaining panel-level key mapping is tracked as an editor-host integration gap rather than a runtime gap.
|
||||||
|
- `LayoutLab` panel now maps concrete arrow/home/end keys into the shared navigation model, with dedicated panel-level coverage proving that the sandbox UI can actually drive the runtime navigation seam end-to-end.
|
||||||
- `new_editor` panel/shell diagnostics improvements for hosted preview state.
|
- `new_editor` panel/shell diagnostics improvements for hosted preview state.
|
||||||
- XCUI asset document loading changed to prefer direct source compilation before `ResourceManager` fallback for the sandbox path, fixing the LayoutLab crash.
|
- XCUI asset document loading changed to prefer direct source compilation before `ResourceManager` fallback for the sandbox path, fixing the LayoutLab crash.
|
||||||
- `UIDocumentCompiler.cpp` repaired enough to restore full local builds after the duplicated schema-helper regression.
|
- `UIDocumentCompiler.cpp` repaired enough to restore full local builds after the duplicated schema-helper regression.
|
||||||
|
|||||||
@@ -46,6 +46,33 @@ const char* GetPreviewStateLabel(
|
|||||||
return previewStats.presented ? "live" : "idle";
|
return previewStats.presented ? "live" : "idle";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShouldCaptureKeyboardNavigation(
|
||||||
|
const ::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession& canvasSession,
|
||||||
|
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameResult& previousFrame) {
|
||||||
|
if (!canvasSession.validCanvas) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return canvasSession.hovered ||
|
||||||
|
(canvasSession.windowFocused &&
|
||||||
|
!previousFrame.stats.selectedElementId.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopulateKeyboardNavigationInput(
|
||||||
|
::XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState& input,
|
||||||
|
bool captureKeyboardNavigation) {
|
||||||
|
if (!captureKeyboardNavigation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.navigatePrevious = ImGui::IsKeyPressed(ImGuiKey_UpArrow);
|
||||||
|
input.navigateNext = ImGui::IsKeyPressed(ImGuiKey_DownArrow);
|
||||||
|
input.navigateHome = ImGui::IsKeyPressed(ImGuiKey_Home);
|
||||||
|
input.navigateEnd = ImGui::IsKeyPressed(ImGuiKey_End);
|
||||||
|
input.navigateCollapse = ImGui::IsKeyPressed(ImGuiKey_LeftArrow);
|
||||||
|
input.navigateExpand = ImGui::IsKeyPressed(ImGuiKey_RightArrow);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
XCUILayoutLabPanel::XCUILayoutLabPanel(::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* inputSource)
|
XCUILayoutLabPanel::XCUILayoutLabPanel(::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* inputSource)
|
||||||
@@ -79,6 +106,10 @@ const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats& XCUILayoutLabPane
|
|||||||
return m_lastPreviewStats;
|
return m_lastPreviewStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool XCUILayoutLabPanel::TryGetElementRect(const std::string& elementId, ::XCEngine::UI::UIRect& outRect) const {
|
||||||
|
return m_runtime.TryGetElementRect(elementId, outRect);
|
||||||
|
}
|
||||||
|
|
||||||
void XCUILayoutLabPanel::SetHostedPreviewPresenter(
|
void XCUILayoutLabPanel::SetHostedPreviewPresenter(
|
||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter) {
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter) {
|
||||||
m_previewPresenter = std::move(previewPresenter);
|
m_previewPresenter = std::move(previewPresenter);
|
||||||
@@ -168,6 +199,9 @@ void XCUILayoutLabPanel::Render() {
|
|||||||
input.pointerInside = validCanvas && canvasSession.hovered;
|
input.pointerInside = validCanvas && canvasSession.hovered;
|
||||||
}
|
}
|
||||||
input.pointerPressed = input.pointerInside && ImGui::IsMouseClicked(ImGuiMouseButton_Left);
|
input.pointerPressed = input.pointerInside && ImGui::IsMouseClicked(ImGuiMouseButton_Left);
|
||||||
|
PopulateKeyboardNavigationInput(
|
||||||
|
input,
|
||||||
|
ShouldCaptureKeyboardNavigation(canvasSession, m_runtime.GetFrameResult()));
|
||||||
|
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameResult& frame = m_runtime.Update(input);
|
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameResult& frame = m_runtime.Update(input);
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "XCUIBackend/XCUILayoutLabRuntime.h"
|
#include "XCUIBackend/XCUILayoutLabRuntime.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
namespace NewEditor {
|
namespace NewEditor {
|
||||||
@@ -31,6 +32,7 @@ public:
|
|||||||
bool IsUsingNativeHostedPreview() const;
|
bool IsUsingNativeHostedPreview() const;
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameResult& GetFrameResult() const;
|
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameResult& GetFrameResult() const;
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats& GetLastPreviewStats() const;
|
const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats& GetLastPreviewStats() const;
|
||||||
|
bool TryGetElementRect(const std::string& elementId, ::XCEngine::UI::UIRect& outRect) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_lastReloadSucceeded = false;
|
bool m_lastReloadSucceeded = false;
|
||||||
|
|||||||
253
tests/NewEditor/test_xcui_layout_lab_panel.cpp
Normal file
253
tests/NewEditor/test_xcui_layout_lab_panel.cpp
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "panels/XCUILayoutLabPanel.h"
|
||||||
|
|
||||||
|
#include "XCUIBackend/XCUIHostedPreviewPresenter.h"
|
||||||
|
#include "XCUIBackend/XCUIPanelCanvasHost.h"
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter;
|
||||||
|
using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost;
|
||||||
|
using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewFrame;
|
||||||
|
using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats;
|
||||||
|
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest;
|
||||||
|
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession;
|
||||||
|
using XCEngine::NewEditor::XCUILayoutLabPanel;
|
||||||
|
|
||||||
|
class ImGuiContextScope {
|
||||||
|
public:
|
||||||
|
ImGuiContextScope() {
|
||||||
|
IMGUI_CHECKVERSION();
|
||||||
|
ImGui::CreateContext();
|
||||||
|
ImGui::StyleColorsDark();
|
||||||
|
}
|
||||||
|
|
||||||
|
~ImGuiContextScope() {
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void PrepareImGui(float width = 1280.0f, float height = 900.0f) {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.DisplaySize = ImVec2(width, height);
|
||||||
|
io.DeltaTime = 1.0f / 60.0f;
|
||||||
|
unsigned char* fontPixels = nullptr;
|
||||||
|
int fontWidth = 0;
|
||||||
|
int fontHeight = 0;
|
||||||
|
io.Fonts->GetTexDataAsRGBA32(&fontPixels, &fontWidth, &fontHeight);
|
||||||
|
io.Fonts->SetTexID(static_cast<ImTextureID>(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
class StubHostedPreviewPresenter final : public IXCUIHostedPreviewPresenter {
|
||||||
|
public:
|
||||||
|
bool Present(const XCUIHostedPreviewFrame& frame) override {
|
||||||
|
m_lastStats = {};
|
||||||
|
m_lastStats.presented = frame.drawData != nullptr;
|
||||||
|
return m_lastStats.presented;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XCUIHostedPreviewStats& GetLastStats() const override {
|
||||||
|
return m_lastStats;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
XCUIHostedPreviewStats m_lastStats = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
class StubCanvasHost final : public IXCUIPanelCanvasHost {
|
||||||
|
public:
|
||||||
|
const char* GetDebugName() const override {
|
||||||
|
return "StubCanvasHost";
|
||||||
|
}
|
||||||
|
|
||||||
|
XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend GetBackend() const override {
|
||||||
|
return XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend::Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostCapabilities GetCapabilities() const override {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
XCUIPanelCanvasSession BeginCanvas(const XCUIPanelCanvasRequest&) override {
|
||||||
|
return m_session;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawFilledRect(
|
||||||
|
const XCEngine::UI::UIRect&,
|
||||||
|
const XCEngine::UI::UIColor&,
|
||||||
|
float) override {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawOutlineRect(
|
||||||
|
const XCEngine::UI::UIRect&,
|
||||||
|
const XCEngine::UI::UIColor&,
|
||||||
|
float,
|
||||||
|
float) override {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawText(
|
||||||
|
const XCEngine::UI::UIPoint&,
|
||||||
|
std::string_view,
|
||||||
|
const XCEngine::UI::UIColor&,
|
||||||
|
float) override {
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndCanvas() override {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPointerPosition(const XCEngine::UI::UIPoint& position) {
|
||||||
|
m_session.pointerPosition = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetHovered(bool hovered) {
|
||||||
|
m_session.hovered = hovered;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetWindowFocused(bool focused) {
|
||||||
|
m_session.windowFocused = focused;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
XCUIPanelCanvasSession m_session = {
|
||||||
|
XCEngine::UI::UIRect(0.0f, 0.0f, 960.0f, 640.0f),
|
||||||
|
XCEngine::UI::UIRect(0.0f, 0.0f, 960.0f, 640.0f),
|
||||||
|
XCEngine::UI::UIPoint(120.0f, 120.0f),
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void RenderPanelFrame(
|
||||||
|
XCUILayoutLabPanel& panel,
|
||||||
|
ImGuiContextScope&,
|
||||||
|
const std::function<void(ImGuiIO&)>& configureIo = nullptr) {
|
||||||
|
PrepareImGui();
|
||||||
|
if (configureIo) {
|
||||||
|
configureIo(ImGui::GetIO());
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::NewFrame();
|
||||||
|
panel.Render();
|
||||||
|
ImGui::Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClickElement(
|
||||||
|
XCUILayoutLabPanel& panel,
|
||||||
|
StubCanvasHost& canvasHost,
|
||||||
|
const std::string& elementId,
|
||||||
|
ImGuiContextScope& contextScope) {
|
||||||
|
XCEngine::UI::UIRect elementRect = {};
|
||||||
|
ASSERT_TRUE(panel.TryGetElementRect(elementId, elementRect));
|
||||||
|
const XCEngine::UI::UIPoint clickPoint(
|
||||||
|
elementRect.x + elementRect.width * 0.5f,
|
||||||
|
elementRect.y + elementRect.height * 0.5f);
|
||||||
|
|
||||||
|
canvasHost.SetPointerPosition(clickPoint);
|
||||||
|
canvasHost.SetHovered(true);
|
||||||
|
RenderPanelFrame(
|
||||||
|
panel,
|
||||||
|
contextScope,
|
||||||
|
[](ImGuiIO& io) {
|
||||||
|
io.AddMouseButtonEvent(ImGuiMouseButton_Left, true);
|
||||||
|
});
|
||||||
|
RenderPanelFrame(
|
||||||
|
panel,
|
||||||
|
contextScope,
|
||||||
|
[](ImGuiIO& io) {
|
||||||
|
io.AddMouseButtonEvent(ImGuiMouseButton_Left, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressKeyOnce(
|
||||||
|
XCUILayoutLabPanel& panel,
|
||||||
|
ImGuiContextScope& contextScope,
|
||||||
|
ImGuiKey key) {
|
||||||
|
RenderPanelFrame(
|
||||||
|
panel,
|
||||||
|
contextScope,
|
||||||
|
[key](ImGuiIO& io) {
|
||||||
|
io.AddKeyEvent(key, true);
|
||||||
|
});
|
||||||
|
RenderPanelFrame(
|
||||||
|
panel,
|
||||||
|
contextScope,
|
||||||
|
[key](ImGuiIO& io) {
|
||||||
|
io.AddKeyEvent(key, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewEditorXCUILayoutLabPanelTest, MapsPreviousNextHomeAndEndIntoRuntimeNavigation) {
|
||||||
|
ImGuiContextScope contextScope;
|
||||||
|
|
||||||
|
auto previewPresenter = std::make_unique<StubHostedPreviewPresenter>();
|
||||||
|
auto canvasHost = std::make_unique<StubCanvasHost>();
|
||||||
|
StubCanvasHost* canvasHostPtr = canvasHost.get();
|
||||||
|
|
||||||
|
XCUILayoutLabPanel panel(nullptr, std::move(previewPresenter));
|
||||||
|
panel.SetHostedPreviewEnabled(false);
|
||||||
|
panel.SetCanvasHost(std::move(canvasHost));
|
||||||
|
|
||||||
|
RenderPanelFrame(panel, contextScope);
|
||||||
|
ClickElement(panel, *canvasHostPtr, "assetLighting", contextScope);
|
||||||
|
ASSERT_EQ(panel.GetFrameResult().stats.selectedElementId, "assetLighting");
|
||||||
|
|
||||||
|
canvasHostPtr->SetHovered(false);
|
||||||
|
canvasHostPtr->SetWindowFocused(true);
|
||||||
|
|
||||||
|
PressKeyOnce(panel, contextScope, ImGuiKey_DownArrow);
|
||||||
|
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "assetMaterials");
|
||||||
|
|
||||||
|
PressKeyOnce(panel, contextScope, ImGuiKey_UpArrow);
|
||||||
|
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "assetLighting");
|
||||||
|
|
||||||
|
PressKeyOnce(panel, contextScope, ImGuiKey_End);
|
||||||
|
const std::string endSelection = panel.GetFrameResult().stats.selectedElementId;
|
||||||
|
ASSERT_FALSE(endSelection.empty());
|
||||||
|
EXPECT_NE(endSelection, "assetLighting");
|
||||||
|
|
||||||
|
PressKeyOnce(panel, contextScope, ImGuiKey_Home);
|
||||||
|
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "assetLighting");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewEditorXCUILayoutLabPanelTest, MapsCollapseAndExpandIntoRuntimeNavigation) {
|
||||||
|
ImGuiContextScope contextScope;
|
||||||
|
|
||||||
|
auto previewPresenter = std::make_unique<StubHostedPreviewPresenter>();
|
||||||
|
auto canvasHost = std::make_unique<StubCanvasHost>();
|
||||||
|
StubCanvasHost* canvasHostPtr = canvasHost.get();
|
||||||
|
|
||||||
|
XCUILayoutLabPanel panel(nullptr, std::move(previewPresenter));
|
||||||
|
panel.SetHostedPreviewEnabled(false);
|
||||||
|
panel.SetCanvasHost(std::move(canvasHost));
|
||||||
|
|
||||||
|
RenderPanelFrame(panel, contextScope);
|
||||||
|
ClickElement(panel, *canvasHostPtr, "treeScenes", contextScope);
|
||||||
|
ASSERT_EQ(panel.GetFrameResult().stats.selectedElementId, "treeScenes");
|
||||||
|
|
||||||
|
canvasHostPtr->SetHovered(false);
|
||||||
|
canvasHostPtr->SetWindowFocused(true);
|
||||||
|
|
||||||
|
PressKeyOnce(panel, contextScope, ImGuiKey_LeftArrow);
|
||||||
|
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "treeAssetsRoot");
|
||||||
|
|
||||||
|
PressKeyOnce(panel, contextScope, ImGuiKey_LeftArrow);
|
||||||
|
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "treeAssetsRoot");
|
||||||
|
EXPECT_EQ(panel.GetFrameResult().stats.expandedTreeItemCount, 0u);
|
||||||
|
|
||||||
|
PressKeyOnce(panel, contextScope, ImGuiKey_RightArrow);
|
||||||
|
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "treeAssetsRoot");
|
||||||
|
EXPECT_EQ(panel.GetFrameResult().stats.expandedTreeItemCount, 1u);
|
||||||
|
|
||||||
|
PressKeyOnce(panel, contextScope, ImGuiKey_RightArrow);
|
||||||
|
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "treeScenes");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
Reference in New Issue
Block a user