#include "XCUIBackend/XCUIShellChromeState.h" namespace XCEngine { namespace Editor { namespace XCUIBackend { namespace { constexpr std::size_t ToIndex(XCUIShellPanelId panelId) { return static_cast(panelId); } constexpr std::string_view kViewMenuLabel = "View"; constexpr std::string_view kXCUIDemoShortcut = "Ctrl+1"; constexpr std::string_view kXCUILayoutLabShortcut = "Ctrl+2"; constexpr std::string_view kNativeBackdropShortcut = "Ctrl+Shift+B"; constexpr std::string_view kPulseAccentShortcut = "Ctrl+Shift+P"; constexpr std::string_view kNativeXCUIOverlayShortcut = "Ctrl+Shift+O"; constexpr std::string_view kHostedPreviewHudShortcut = "Ctrl+Shift+H"; constexpr std::string_view kNativeDemoPanelPreviewShortcut = "Ctrl+Alt+1"; constexpr std::string_view kNativeLayoutLabPreviewShortcut = "Ctrl+Alt+2"; } // namespace XCUIShellChromeState::XCUIShellChromeState() { m_panels[ToIndex(XCUIShellPanelId::XCUIDemo)] = { XCUIShellPanelId::XCUIDemo, "XCUI Demo", "XCUI Demo", "new_editor.panels.xcui_demo", true, true, XCUIShellHostedPreviewMode::NativeOffscreen }; m_panels[ToIndex(XCUIShellPanelId::XCUILayoutLab)] = { XCUIShellPanelId::XCUILayoutLab, "XCUI Layout Lab", "XCUI Layout Lab", "new_editor.panels.xcui_layout_lab", true, true, XCUIShellHostedPreviewMode::HostedPresenter }; } const XCUIShellViewToggleState& XCUIShellChromeState::GetViewToggles() const { return m_viewToggles; } const std::array(XCUIShellPanelId::Count)>& XCUIShellChromeState::GetPanels() const { return m_panels; } const XCUIShellPanelChromeState* XCUIShellChromeState::TryGetPanelState(XCUIShellPanelId panelId) const { const std::size_t index = ToIndex(panelId); if (index >= m_panels.size()) { return nullptr; } return &m_panels[index]; } XCUIShellPanelChromeState* XCUIShellChromeState::TryGetPanelStateMutable(XCUIShellPanelId panelId) { const std::size_t index = ToIndex(panelId); if (index >= m_panels.size()) { return nullptr; } return &m_panels[index]; } bool XCUIShellChromeState::IsPanelVisible(XCUIShellPanelId panelId) const { const XCUIShellPanelChromeState* panelState = TryGetPanelState(panelId); return panelState != nullptr && panelState->visible; } bool XCUIShellChromeState::SetPanelVisible(XCUIShellPanelId panelId, bool visible) { XCUIShellPanelChromeState* panelState = TryGetPanelStateMutable(panelId); if (panelState == nullptr || panelState->visible == visible) { return false; } panelState->visible = visible; return true; } bool XCUIShellChromeState::TogglePanelVisible(XCUIShellPanelId panelId) { XCUIShellPanelChromeState* panelState = TryGetPanelStateMutable(panelId); if (panelState == nullptr) { return false; } panelState->visible = !panelState->visible; return true; } bool XCUIShellChromeState::IsHostedPreviewEnabled(XCUIShellPanelId panelId) const { const XCUIShellPanelChromeState* panelState = TryGetPanelState(panelId); return panelState != nullptr && panelState->hostedPreviewEnabled; } bool XCUIShellChromeState::SetHostedPreviewEnabled(XCUIShellPanelId panelId, bool enabled) { XCUIShellPanelChromeState* panelState = TryGetPanelStateMutable(panelId); if (panelState == nullptr || panelState->hostedPreviewEnabled == enabled) { return false; } panelState->hostedPreviewEnabled = enabled; return true; } XCUIShellHostedPreviewMode XCUIShellChromeState::GetHostedPreviewMode(XCUIShellPanelId panelId) const { const XCUIShellPanelChromeState* panelState = TryGetPanelState(panelId); return panelState != nullptr ? panelState->previewMode : XCUIShellHostedPreviewMode::HostedPresenter; } XCUIShellHostedPreviewState XCUIShellChromeState::GetHostedPreviewState(XCUIShellPanelId panelId) const { const XCUIShellPanelChromeState* panelState = TryGetPanelState(panelId); if (panelState == nullptr || !panelState->hostedPreviewEnabled) { return XCUIShellHostedPreviewState::Disabled; } return panelState->previewMode == XCUIShellHostedPreviewMode::NativeOffscreen ? XCUIShellHostedPreviewState::NativeOffscreen : XCUIShellHostedPreviewState::HostedPresenter; } bool XCUIShellChromeState::IsNativeHostedPreviewActive(XCUIShellPanelId panelId) const { return GetHostedPreviewState(panelId) == XCUIShellHostedPreviewState::NativeOffscreen; } bool XCUIShellChromeState::IsHostedPresenterPreviewActive(XCUIShellPanelId panelId) const { return GetHostedPreviewState(panelId) == XCUIShellHostedPreviewState::HostedPresenter; } bool XCUIShellChromeState::SetHostedPreviewMode( XCUIShellPanelId panelId, XCUIShellHostedPreviewMode mode) { XCUIShellPanelChromeState* panelState = TryGetPanelStateMutable(panelId); if (panelState == nullptr || panelState->previewMode == mode) { return false; } panelState->previewMode = mode; return true; } bool XCUIShellChromeState::ToggleHostedPreviewMode(XCUIShellPanelId panelId) { XCUIShellPanelChromeState* panelState = TryGetPanelStateMutable(panelId); if (panelState == nullptr) { return false; } panelState->previewMode = panelState->previewMode == XCUIShellHostedPreviewMode::NativeOffscreen ? XCUIShellHostedPreviewMode::HostedPresenter : XCUIShellHostedPreviewMode::NativeOffscreen; return true; } bool XCUIShellChromeState::GetViewToggle(XCUIShellViewToggleId toggleId) const { switch (toggleId) { case XCUIShellViewToggleId::NativeBackdrop: return m_viewToggles.nativeBackdropVisible; case XCUIShellViewToggleId::PulseAccent: return m_viewToggles.pulseAccentEnabled; case XCUIShellViewToggleId::NativeXCUIOverlay: return m_viewToggles.nativeXCUIOverlayVisible; case XCUIShellViewToggleId::HostedPreviewHud: return m_viewToggles.hostedPreviewHudVisible; case XCUIShellViewToggleId::Count: default: return false; } } bool XCUIShellChromeState::SetViewToggle(XCUIShellViewToggleId toggleId, bool enabled) { bool* target = nullptr; switch (toggleId) { case XCUIShellViewToggleId::NativeBackdrop: target = &m_viewToggles.nativeBackdropVisible; break; case XCUIShellViewToggleId::PulseAccent: target = &m_viewToggles.pulseAccentEnabled; break; case XCUIShellViewToggleId::NativeXCUIOverlay: target = &m_viewToggles.nativeXCUIOverlayVisible; break; case XCUIShellViewToggleId::HostedPreviewHud: target = &m_viewToggles.hostedPreviewHudVisible; break; case XCUIShellViewToggleId::Count: default: return false; } if (*target == enabled) { return false; } *target = enabled; return true; } bool XCUIShellChromeState::ToggleViewToggle(XCUIShellViewToggleId toggleId) { return SetViewToggle(toggleId, !GetViewToggle(toggleId)); } bool XCUIShellChromeState::HasCommand(std::string_view commandId) const { XCUIShellCommandDescriptor descriptor = {}; return TryGetCommandDescriptor(commandId, descriptor); } bool XCUIShellChromeState::InvokeCommand(std::string_view commandId) { if (commandId == XCUIShellChromeCommandIds::ToggleXCUIDemoPanel) { return TogglePanelVisible(XCUIShellPanelId::XCUIDemo); } if (commandId == XCUIShellChromeCommandIds::ToggleXCUILayoutLabPanel) { return TogglePanelVisible(XCUIShellPanelId::XCUILayoutLab); } if (commandId == XCUIShellChromeCommandIds::ToggleNativeBackdrop) { return ToggleViewToggle(XCUIShellViewToggleId::NativeBackdrop); } if (commandId == XCUIShellChromeCommandIds::TogglePulseAccent) { return ToggleViewToggle(XCUIShellViewToggleId::PulseAccent); } if (commandId == XCUIShellChromeCommandIds::ToggleNativeXCUIOverlay) { return ToggleViewToggle(XCUIShellViewToggleId::NativeXCUIOverlay); } if (commandId == XCUIShellChromeCommandIds::ToggleHostedPreviewHud) { return ToggleViewToggle(XCUIShellViewToggleId::HostedPreviewHud); } if (commandId == XCUIShellChromeCommandIds::ToggleNativeDemoPanelPreview) { return ToggleHostedPreviewMode(XCUIShellPanelId::XCUIDemo); } if (commandId == XCUIShellChromeCommandIds::ToggleNativeLayoutLabPreview) { return ToggleHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab); } return false; } bool XCUIShellChromeState::TryGetCommandDescriptor( std::string_view commandId, XCUIShellCommandDescriptor& outDescriptor) const { outDescriptor = {}; outDescriptor.checkable = false; outDescriptor.enabled = false; const auto tryBuildPanelVisibilityDescriptor = [this, commandId, &outDescriptor]( XCUIShellPanelId panelId, std::string_view shortcut) { if (commandId != GetPanelVisibilityCommandId(panelId)) { return false; } const XCUIShellPanelChromeState* panelState = TryGetPanelState(panelId); if (panelState == nullptr) { return false; } outDescriptor.label = panelState->panelTitle; outDescriptor.shortcut = shortcut; outDescriptor.commandId = commandId; outDescriptor.checkable = true; outDescriptor.checked = panelState->visible; outDescriptor.enabled = true; return true; }; if (tryBuildPanelVisibilityDescriptor(XCUIShellPanelId::XCUIDemo, kXCUIDemoShortcut)) { return true; } if (tryBuildPanelVisibilityDescriptor(XCUIShellPanelId::XCUILayoutLab, kXCUILayoutLabShortcut)) { return true; } if (commandId == GetViewToggleCommandId(XCUIShellViewToggleId::NativeBackdrop)) { outDescriptor.label = "Native Backdrop"; outDescriptor.shortcut = kNativeBackdropShortcut; outDescriptor.commandId = commandId; outDescriptor.checkable = true; outDescriptor.checked = GetViewToggle(XCUIShellViewToggleId::NativeBackdrop); outDescriptor.enabled = true; return true; } if (commandId == GetViewToggleCommandId(XCUIShellViewToggleId::PulseAccent)) { outDescriptor.label = "Pulse Accent"; outDescriptor.shortcut = kPulseAccentShortcut; outDescriptor.commandId = commandId; outDescriptor.checkable = true; outDescriptor.checked = GetViewToggle(XCUIShellViewToggleId::PulseAccent); outDescriptor.enabled = true; return true; } if (commandId == GetViewToggleCommandId(XCUIShellViewToggleId::NativeXCUIOverlay)) { outDescriptor.label = "Native XCUI Overlay"; outDescriptor.shortcut = kNativeXCUIOverlayShortcut; outDescriptor.commandId = commandId; outDescriptor.checkable = true; outDescriptor.checked = GetViewToggle(XCUIShellViewToggleId::NativeXCUIOverlay); outDescriptor.enabled = true; return true; } if (commandId == GetViewToggleCommandId(XCUIShellViewToggleId::HostedPreviewHud)) { outDescriptor.label = "Hosted Preview HUD"; outDescriptor.shortcut = kHostedPreviewHudShortcut; outDescriptor.commandId = commandId; outDescriptor.checkable = true; outDescriptor.checked = GetViewToggle(XCUIShellViewToggleId::HostedPreviewHud); outDescriptor.enabled = true; return true; } if (commandId == GetPanelPreviewModeCommandId(XCUIShellPanelId::XCUIDemo)) { outDescriptor.label = "Native Demo Panel Preview"; outDescriptor.shortcut = kNativeDemoPanelPreviewShortcut; outDescriptor.commandId = commandId; outDescriptor.checkable = true; outDescriptor.checked = IsNativeHostedPreviewActive(XCUIShellPanelId::XCUIDemo); outDescriptor.enabled = true; return true; } if (commandId == GetPanelPreviewModeCommandId(XCUIShellPanelId::XCUILayoutLab)) { outDescriptor.label = "Native Layout Lab Preview"; outDescriptor.shortcut = kNativeLayoutLabPreviewShortcut; outDescriptor.commandId = commandId; outDescriptor.checkable = true; outDescriptor.checked = IsNativeHostedPreviewActive(XCUIShellPanelId::XCUILayoutLab); outDescriptor.enabled = true; return true; } return false; } XCUIShellMenuDescriptor XCUIShellChromeState::BuildViewMenuDescriptor() const { XCUIShellMenuDescriptor descriptor = {}; descriptor.label = kViewMenuLabel; descriptor.items.reserve(9u); const auto appendCommandItem = [this, &descriptor](std::string_view commandId) { XCUIShellCommandDescriptor commandDescriptor = {}; if (!TryGetCommandDescriptor(commandId, commandDescriptor)) { return; } XCUIShellMenuItemDescriptor item = {}; item.kind = XCUIShellMenuItemKind::Command; item.command = commandDescriptor; descriptor.items.push_back(item); }; appendCommandItem(GetPanelVisibilityCommandId(XCUIShellPanelId::XCUIDemo)); appendCommandItem(GetPanelVisibilityCommandId(XCUIShellPanelId::XCUILayoutLab)); descriptor.items.push_back({ XCUIShellMenuItemKind::Separator, {} }); appendCommandItem(GetViewToggleCommandId(XCUIShellViewToggleId::NativeBackdrop)); appendCommandItem(GetViewToggleCommandId(XCUIShellViewToggleId::PulseAccent)); appendCommandItem(GetViewToggleCommandId(XCUIShellViewToggleId::NativeXCUIOverlay)); appendCommandItem(GetViewToggleCommandId(XCUIShellViewToggleId::HostedPreviewHud)); appendCommandItem(GetPanelPreviewModeCommandId(XCUIShellPanelId::XCUIDemo)); appendCommandItem(GetPanelPreviewModeCommandId(XCUIShellPanelId::XCUILayoutLab)); return descriptor; } std::string_view XCUIShellChromeState::GetPanelVisibilityCommandId(XCUIShellPanelId panelId) { switch (panelId) { case XCUIShellPanelId::XCUIDemo: return XCUIShellChromeCommandIds::ToggleXCUIDemoPanel; case XCUIShellPanelId::XCUILayoutLab: return XCUIShellChromeCommandIds::ToggleXCUILayoutLabPanel; case XCUIShellPanelId::Count: default: return {}; } } std::string_view XCUIShellChromeState::GetPanelPreviewModeCommandId(XCUIShellPanelId panelId) { switch (panelId) { case XCUIShellPanelId::XCUIDemo: return XCUIShellChromeCommandIds::ToggleNativeDemoPanelPreview; case XCUIShellPanelId::XCUILayoutLab: return XCUIShellChromeCommandIds::ToggleNativeLayoutLabPreview; case XCUIShellPanelId::Count: default: return {}; } } std::string_view XCUIShellChromeState::GetViewToggleCommandId(XCUIShellViewToggleId toggleId) { switch (toggleId) { case XCUIShellViewToggleId::NativeBackdrop: return XCUIShellChromeCommandIds::ToggleNativeBackdrop; case XCUIShellViewToggleId::PulseAccent: return XCUIShellChromeCommandIds::TogglePulseAccent; case XCUIShellViewToggleId::NativeXCUIOverlay: return XCUIShellChromeCommandIds::ToggleNativeXCUIOverlay; case XCUIShellViewToggleId::HostedPreviewHud: return XCUIShellChromeCommandIds::ToggleHostedPreviewHud; case XCUIShellViewToggleId::Count: default: return {}; } } } // namespace XCUIBackend } // namespace Editor } // namespace XCEngine