#include #include #include #include namespace XCEngine::UI::Editor { namespace { using HostStateMap = std::unordered_map; HostStateMap BuildHostStateMap(const std::vector& states) { HostStateMap map = {}; map.reserve(states.size()); for (const UIEditorPanelHostState& state : states) { map.emplace(state.panelId, &state); } return map; } const UIEditorPanelHostState* FindHostState( const std::vector& states, std::string_view panelId) { for (const UIEditorPanelHostState& state : states) { if (state.panelId == panelId) { return &state; } } return nullptr; } void AppendLeaveEvents( std::vector& events, const std::vector& previousStates, const HostStateMap& currentStateMap) { auto appendCategory = [&](auto predicate, UIEditorPanelHostLifecycleEventKind kind) { for (const UIEditorPanelHostState& previous : previousStates) { const UIEditorPanelHostState emptyState = {}; const UIEditorPanelHostState& current = currentStateMap.contains(previous.panelId) ? *currentStateMap.at(previous.panelId) : emptyState; if (predicate(previous, current)) { events.push_back({ kind, previous.panelId }); } } }; appendCategory( [](const UIEditorPanelHostState& previous, const UIEditorPanelHostState& current) { return previous.focused && !current.focused; }, UIEditorPanelHostLifecycleEventKind::FocusLost); appendCategory( [](const UIEditorPanelHostState& previous, const UIEditorPanelHostState& current) { return previous.active && !current.active; }, UIEditorPanelHostLifecycleEventKind::Deactivated); appendCategory( [](const UIEditorPanelHostState& previous, const UIEditorPanelHostState& current) { return previous.visible && !current.visible; }, UIEditorPanelHostLifecycleEventKind::Hidden); appendCategory( [](const UIEditorPanelHostState& previous, const UIEditorPanelHostState& current) { return previous.attached && !current.attached; }, UIEditorPanelHostLifecycleEventKind::Detached); } void AppendEnterEvents( std::vector& events, const std::vector& currentStates, const HostStateMap& previousStateMap) { auto appendCategory = [&](auto predicate, UIEditorPanelHostLifecycleEventKind kind) { for (const UIEditorPanelHostState& current : currentStates) { const UIEditorPanelHostState emptyState = {}; const UIEditorPanelHostState& previous = previousStateMap.contains(current.panelId) ? *previousStateMap.at(current.panelId) : emptyState; if (predicate(previous, current)) { events.push_back({ kind, current.panelId }); } } }; appendCategory( [](const UIEditorPanelHostState& previous, const UIEditorPanelHostState& current) { return !previous.attached && current.attached; }, UIEditorPanelHostLifecycleEventKind::Attached); appendCategory( [](const UIEditorPanelHostState& previous, const UIEditorPanelHostState& current) { return !previous.visible && current.visible; }, UIEditorPanelHostLifecycleEventKind::Shown); appendCategory( [](const UIEditorPanelHostState& previous, const UIEditorPanelHostState& current) { return !previous.active && current.active; }, UIEditorPanelHostLifecycleEventKind::Activated); appendCategory( [](const UIEditorPanelHostState& previous, const UIEditorPanelHostState& current) { return !previous.focused && current.focused; }, UIEditorPanelHostLifecycleEventKind::FocusGained); } std::vector BuildResolvedPanelHostStates( const UIEditorPanelRegistry& panelRegistry, const UIEditorWorkspaceModel& workspace, const UIEditorWorkspaceSession& session, const UIEditorPanelHostLifecycleRequest& request) { const std::vector visiblePanels = CollectUIEditorWorkspaceVisiblePanels(workspace, session); std::unordered_set visiblePanelIds = {}; visiblePanelIds.reserve(visiblePanels.size()); for (const UIEditorWorkspaceVisiblePanel& panel : visiblePanels) { visiblePanelIds.insert(panel.panelId); } std::vector states = {}; states.reserve(panelRegistry.panels.size()); for (const UIEditorPanelDescriptor& descriptor : panelRegistry.panels) { if (!ContainsUIEditorWorkspacePanel(workspace, descriptor.panelId)) { continue; } const UIEditorPanelSessionState* sessionState = FindUIEditorPanelSessionState(session, descriptor.panelId); if (sessionState == nullptr) { continue; } UIEditorPanelHostState state = {}; state.panelId = descriptor.panelId; state.attached = sessionState->open; state.visible = state.attached && visiblePanelIds.contains(state.panelId); state.active = state.visible && workspace.activePanelId == state.panelId; state.focused = state.active && request.focusedPanelId == state.panelId; states.push_back(std::move(state)); } return states; } } // namespace std::string_view GetUIEditorPanelHostLifecycleEventKindName( UIEditorPanelHostLifecycleEventKind kind) { switch (kind) { case UIEditorPanelHostLifecycleEventKind::Attached: return "Attached"; case UIEditorPanelHostLifecycleEventKind::Detached: return "Detached"; case UIEditorPanelHostLifecycleEventKind::Shown: return "Shown"; case UIEditorPanelHostLifecycleEventKind::Hidden: return "Hidden"; case UIEditorPanelHostLifecycleEventKind::Activated: return "Activated"; case UIEditorPanelHostLifecycleEventKind::Deactivated: return "Deactivated"; case UIEditorPanelHostLifecycleEventKind::FocusGained: return "FocusGained"; case UIEditorPanelHostLifecycleEventKind::FocusLost: return "FocusLost"; } return "Unknown"; } const UIEditorPanelHostState* FindUIEditorPanelHostState( const UIEditorPanelHostLifecycleState& state, std::string_view panelId) { return FindHostState(state.panelStates, panelId); } const UIEditorPanelHostState* FindUIEditorPanelHostState( const UIEditorPanelHostLifecycleFrame& frame, std::string_view panelId) { return FindHostState(frame.panelStates, panelId); } UIEditorPanelHostLifecycleFrame UpdateUIEditorPanelHostLifecycle( UIEditorPanelHostLifecycleState& state, const UIEditorPanelRegistry& panelRegistry, const UIEditorWorkspaceModel& workspace, const UIEditorWorkspaceSession& session, const UIEditorPanelHostLifecycleRequest& request) { UIEditorPanelHostLifecycleFrame frame = {}; frame.panelStates = BuildResolvedPanelHostStates(panelRegistry, workspace, session, request); const HostStateMap previousStateMap = BuildHostStateMap(state.panelStates); const HostStateMap currentStateMap = BuildHostStateMap(frame.panelStates); AppendLeaveEvents(frame.events, state.panelStates, currentStateMap); AppendEnterEvents(frame.events, frame.panelStates, previousStateMap); state.panelStates = frame.panelStates; return frame; } } // namespace XCEngine::UI::Editor