#pragma once #ifndef NOMINMAX #define NOMINMAX #endif #include #include #include #include #include #include #include #include #include namespace XCEngine::UI::Editor::App { class EditorContext; class EditorWindow; struct EditorWindowHostConfig { HINSTANCE hInstance = nullptr; const wchar_t* windowClassName = L""; DWORD windowStyle = 0; const wchar_t* primaryWindowTitle = L""; void* windowUserData = nullptr; }; class EditorWindowManager final { public: struct CreateParams { std::string windowId = {}; std::wstring title = {}; int initialX = CW_USEDEFAULT; int initialY = CW_USEDEFAULT; int initialWidth = 1540; int initialHeight = 940; int showCommand = SW_SHOW; bool primary = false; bool autoCaptureOnStartup = false; }; EditorWindowManager( EditorWindowHostConfig hostConfig, std::filesystem::path repoRoot, EditorContext& editorContext); ~EditorWindowManager(); EditorWindowManager(const EditorWindowManager&) = delete; EditorWindowManager& operator=(const EditorWindowManager&) = delete; EditorWindowManager(EditorWindowManager&&) = delete; EditorWindowManager& operator=(EditorWindowManager&&) = delete; EditorWindow* CreateEditorWindow( UIEditorWorkspaceController workspaceController, const CreateParams& params); void HandlePendingNativeWindowCreated(HWND hwnd); void Shutdown(); EditorWindow* FindWindow(HWND hwnd); const EditorWindow* FindWindow(HWND hwnd) const; EditorWindow* FindWindow(std::string_view windowId); const EditorWindow* FindWindow(std::string_view windowId) const; EditorWindow* FindPrimaryWindow(); const EditorWindow* FindPrimaryWindow() const; bool HasWindows() const; void DestroyClosedWindows(); void RenderAllWindows(); bool IsGlobalTabDragActive() const; bool OwnsActiveGlobalTabDrag(std::string_view windowId) const; void EndGlobalTabDragSession(); void HandleDestroyedWindow(HWND hwnd); bool HandleGlobalTabDragPointerMove(HWND hwnd); bool HandleGlobalTabDragPointerButtonUp(HWND hwnd); void ProcessPendingGlobalTabDragStarts(); void ProcessPendingDetachRequests(); private: struct GlobalTabDragSession { bool active = false; std::string panelWindowId = {}; std::string sourceNodeId = {}; std::string panelId = {}; POINT screenPoint = {}; }; void DestroyEditorWindow(EditorWindow& window); UIEditorWindowWorkspaceSet BuildWindowWorkspaceSet( std::string_view activeWindowId = {}) const; UIEditorWindowWorkspaceController BuildLiveWindowWorkspaceController( std::string_view activeWindowId) const; bool SynchronizeWindowsFromWindowSet( const UIEditorWindowWorkspaceSet& windowSet, std::string_view preferredNewWindowId, const POINT& preferredScreenPoint); bool SynchronizeWindowsFromController( const UIEditorWindowWorkspaceController& windowWorkspaceController, std::string_view preferredNewWindowId, const POINT& preferredScreenPoint); UIEditorWorkspaceController BuildWorkspaceControllerForWindow( const UIEditorWindowWorkspaceState& windowState) const; std::wstring BuildWindowTitle( const UIEditorWorkspaceController& workspaceController) const; RECT BuildDetachedWindowRect(const POINT& screenPoint) const; void BeginGlobalTabDragSession( std::string_view panelWindowId, std::string_view sourceNodeId, std::string_view panelId, const POINT& screenPoint); EditorWindow* FindTopmostWindowAtScreenPoint( const POINT& screenPoint, std::string_view excludedWindowId = {}); const EditorWindow* FindTopmostWindowAtScreenPoint( const POINT& screenPoint, std::string_view excludedWindowId = {}) const; bool TryStartGlobalTabDrag(EditorWindow& sourceWindow); bool TryProcessDetachRequest(EditorWindow& sourceWindow); void LogRuntimeTrace(std::string_view channel, std::string_view message) const; EditorWindowHostConfig m_hostConfig = {}; std::filesystem::path m_repoRoot = {}; EditorContext& m_editorContext; std::vector> m_windows = {}; GlobalTabDragSession m_globalTabDragSession = {}; EditorWindow* m_pendingCreateWindow = nullptr; }; } // namespace XCEngine::UI::Editor::App