diff options
Diffstat (limited to 'core/src')
56 files changed, 1293 insertions, 600 deletions
diff --git a/core/src/Entrypoint/Backend.hpp b/core/src/Entrypoint/Backend.hpp index 9ceccb1..ca391e6 100644 --- a/core/src/Entrypoint/Backend.hpp +++ b/core/src/Entrypoint/Backend.hpp @@ -2,7 +2,8 @@ #include <memory> -class RenderingBackend { +class RenderingBackend +{ public: // Implemented in Backend_OpenGL2.cpp static std::unique_ptr<RenderingBackend> CreateOpenGL2Backend(); diff --git a/core/src/Entrypoint/Backend_DirectX11.cpp b/core/src/Entrypoint/Backend_DirectX11.cpp index 8d46bf4..4dc33f7 100644 --- a/core/src/Entrypoint/Backend_DirectX11.cpp +++ b/core/src/Entrypoint/Backend_DirectX11.cpp @@ -11,7 +11,8 @@ // Forward declare message handler from imgui_impl_win32.cpp extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -class DirectX11Backend : public RenderingBackend { +class DirectX11Backend : public RenderingBackend +{ private: HWND hWnd; WNDCLASSEX wc; @@ -22,7 +23,8 @@ private: ID3D11RenderTargetView* mMainRenderTargetView = nullptr; public: - DirectX11Backend() { + DirectX11Backend() + { ImGui_ImplWin32_EnableDpiAwareness(); wc.cbSize = sizeof(WNDCLASSEX); @@ -68,7 +70,8 @@ public: ImGui_ImplDX11_Init(mD3dDevice, mD3dDeviceContext); } - virtual ~DirectX11Backend() { + virtual ~DirectX11Backend() + { ImGui_ImplDX11_Shutdown(); ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext(); @@ -78,7 +81,8 @@ public: ::UnregisterClass(wc.lpszClassName, wc.hInstance); } - virtual void RunUntilWindowClose(void (*windowContent)()) { + virtual void RunUntilWindowClose(void (*windowContent)()) + { while (true) { MSG msg; bool done = false; @@ -109,7 +113,8 @@ public: } private: - bool CreateDeviceD3D() { + bool CreateDeviceD3D() + { // Setup swap chain DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); @@ -142,7 +147,8 @@ private: return true; } - void CleanupDeviceD3D() { + void CleanupDeviceD3D() + { CleanupRenderTarget(); if (mSwapChain) { mSwapChain->Release(); @@ -158,21 +164,24 @@ private: } } - void CreateRenderTarget() { + void CreateRenderTarget() + { ID3D11Texture2D* pBackBuffer; mSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); mD3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &mMainRenderTargetView); pBackBuffer->Release(); } - void CleanupRenderTarget() { + void CleanupRenderTarget() + { if (mMainRenderTargetView) { mMainRenderTargetView->Release(); mMainRenderTargetView = nullptr; } } - static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { DirectX11Backend* self; if (uMsg == WM_NCCREATE) { auto lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam); @@ -190,7 +199,8 @@ private: } } - LRESULT WndProc(UINT msg, WPARAM wParam, LPARAM lParam) { + LRESULT WndProc(UINT msg, WPARAM wParam, LPARAM lParam) + { if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) { return true; } @@ -221,7 +231,8 @@ private: } }; -std::unique_ptr<RenderingBackend> RenderingBackend::CreateDx11Backend() { +std::unique_ptr<RenderingBackend> RenderingBackend::CreateDx11Backend() +{ try { return std::make_unique<DirectX11Backend>(); } catch (std::exception& e) { @@ -231,7 +242,8 @@ std::unique_ptr<RenderingBackend> RenderingBackend::CreateDx11Backend() { #else // ^^ BUILD_CORE_WITH_DX11_BACKEND | BUILD_CORE_WITH_DX11_BACKEND vv -std::unique_ptr<RenderingBackend> RenderingBackend::CreateDx11Backend() { +std::unique_ptr<RenderingBackend> RenderingBackend::CreateDx11Backend() +{ return nullptr; } diff --git a/core/src/Entrypoint/Backend_DirectX12.cpp b/core/src/Entrypoint/Backend_DirectX12.cpp index c0492c2..fd4a531 100644 --- a/core/src/Entrypoint/Backend_DirectX12.cpp +++ b/core/src/Entrypoint/Backend_DirectX12.cpp @@ -15,9 +15,11 @@ constexpr int kNumBackBuffers = 3; // Forward declare message handler from imgui_impl_win32.cpp extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -class DirectX12Backend : public RenderingBackend { +class DirectX12Backend : public RenderingBackend +{ private: - struct FrameContext { + struct FrameContext + { ID3D12CommandAllocator* CommandAllocator; UINT64 FenceValue; }; @@ -42,7 +44,8 @@ private: D3D12_CPU_DESCRIPTOR_HANDLE mMainRenderTargetDescriptor[kNumBackBuffers] = {}; public: - DirectX12Backend() { + DirectX12Backend() + { ImGui_ImplWin32_EnableDpiAwareness(); wc.cbSize = sizeof(WNDCLASSEX); @@ -88,7 +91,8 @@ public: ImGui_ImplDX12_Init(mD3dDevice, kNumFramesInFlight, DXGI_FORMAT_R8G8B8A8_UNORM, mD3dSrvDescHeap, mD3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), mD3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart()); } - virtual ~DirectX12Backend() { + virtual ~DirectX12Backend() + { WaitForLastSubmittedFrame(); // Cleanup @@ -101,7 +105,8 @@ public: ::UnregisterClass(wc.lpszClassName, wc.hInstance); } - virtual void RunUntilWindowClose(void (*windowContent)()) { + virtual void RunUntilWindowClose(void (*windowContent)()) + { while (true) { MSG msg; bool done = false; @@ -161,7 +166,8 @@ public: } private: - bool CreateDeviceD3D() { + bool CreateDeviceD3D() + { // Setup swap chain DXGI_SWAP_CHAIN_DESC1 sd; { @@ -260,7 +266,8 @@ private: return true; } - void CleanupDeviceD3D() { + void CleanupDeviceD3D() + { CleanupRenderTarget(); if (mSwapChain) { mSwapChain->Release(); @@ -304,7 +311,8 @@ private: } } - void CreateRenderTarget() { + void CreateRenderTarget() + { for (UINT i = 0; i < kNumBackBuffers; i++) { ID3D12Resource* pBackBuffer = nullptr; @@ -314,7 +322,8 @@ private: } } - void CleanupRenderTarget() { + void CleanupRenderTarget() + { WaitForLastSubmittedFrame(); for (UINT i = 0; i < kNumBackBuffers; i++) @@ -324,7 +333,8 @@ private: } } - void WaitForLastSubmittedFrame() { + void WaitForLastSubmittedFrame() + { FrameContext* frameCtx = &mFrameContext[mFrameIndex % kNumFramesInFlight]; UINT64 fenceValue = frameCtx->FenceValue; @@ -339,7 +349,8 @@ private: WaitForSingleObject(mFenceEvent, INFINITE); } - FrameContext* WaitForNextFrameResources() { + FrameContext* WaitForNextFrameResources() + { UINT nextFrameIndex = mFrameIndex + 1; mFrameIndex = nextFrameIndex; @@ -361,7 +372,8 @@ private: return frameCtx; } - void ResizeSwapChain(int width, int height) { + void ResizeSwapChain(int width, int height) + { DXGI_SWAP_CHAIN_DESC1 sd; mSwapChain->GetDesc1(&sd); sd.Width = width; @@ -385,7 +397,8 @@ private: assert(mSwapChainWaitableObject != nullptr); } - static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { DirectX12Backend* self; if (uMsg == WM_NCCREATE) { auto lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam); @@ -403,7 +416,8 @@ private: } } - LRESULT WndProc(UINT msg, WPARAM wParam, LPARAM lParam) { + LRESULT WndProc(UINT msg, WPARAM wParam, LPARAM lParam) + { if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) { return true; } @@ -437,7 +451,8 @@ private: } }; -std::unique_ptr<RenderingBackend> RenderingBackend::CreateDx12Backend() { +std::unique_ptr<RenderingBackend> RenderingBackend::CreateDx12Backend() +{ try { return std::make_unique<DirectX12Backend>(); } catch (std::exception& e) { @@ -447,7 +462,8 @@ std::unique_ptr<RenderingBackend> RenderingBackend::CreateDx12Backend() { #else // ^^ BUILD_CORE_WITH_DX12_BACKEND | BUILD_CORE_WITH_DX12_BACKEND vv -std::unique_ptr<RenderingBackend> RenderingBackend::CreateDx12Backend() { +std::unique_ptr<RenderingBackend> RenderingBackend::CreateDx12Backend() +{ return nullptr; } diff --git a/core/src/Entrypoint/Backend_Metal.mm b/core/src/Entrypoint/Backend_Metal.mm index a1f4993..276bef2 100644 --- a/core/src/Entrypoint/Backend_Metal.mm +++ b/core/src/Entrypoint/Backend_Metal.mm @@ -2,22 +2,27 @@ #if BUILD_CORE_WITH_METAL_BACKEND -class MetalBackend : public RenderingBackend { +class MetalBackend : public RenderingBackend +{ public: - MetalBackend() { + MetalBackend() + { // TODO } - virtual ~MetalBackend() { + virtual ~MetalBackend() + { // TODO } - virtual void RunUntilWindowClose(void (*windowContent)()) { + virtual void RunUntilWindowClose(void (*windowContent)()) + { // TODO } }; -std::unique_ptr<RenderingBackend> RenderingBackend::CreateMetalBackend() { +std::unique_ptr<RenderingBackend> RenderingBackend::CreateMetalBackend() +{ try { return std::make_unique<MetalBackend>(); } catch (std::exception& e) { @@ -27,7 +32,8 @@ std::unique_ptr<RenderingBackend> RenderingBackend::CreateMetalBackend() { #else // ^^ BUILD_CORE_WITH_METAL_BACKEND | BUILD_CORE_WITH_METAL_BACKEND vv -std::unique_ptr<RenderingBackend> RenderingBackend::CreateMetalBackend() { +std::unique_ptr<RenderingBackend> RenderingBackend::CreateMetalBackend() +{ return nullptr; } diff --git a/core/src/Entrypoint/Backend_OpenGL2.cpp b/core/src/Entrypoint/Backend_OpenGL2.cpp index 422ad91..8c56b81 100644 --- a/core/src/Entrypoint/Backend_OpenGL2.cpp +++ b/core/src/Entrypoint/Backend_OpenGL2.cpp @@ -12,12 +12,14 @@ # define IMGUI_IMPL_OPENGL_LOADER_GLAD # include <backend/imgui_impl_opengl2.cpp> -class OpenGL2Backend : public RenderingBackend { +class OpenGL2Backend : public RenderingBackend +{ private: GLFWwindow* mWindow; public: - OpenGL2Backend() { + OpenGL2Backend() + { glfwSetErrorCallback(&GlfwErrorCallback); if (!glfwInit()) { throw std::runtime_error("Failed to initialize GLFW."); @@ -41,7 +43,8 @@ public: ImGui_ImplOpenGL2_Init(); } - virtual ~OpenGL2Backend() { + virtual ~OpenGL2Backend() + { ImGui_ImplOpenGL2_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); @@ -50,7 +53,8 @@ public: glfwTerminate(); } - virtual void RunUntilWindowClose(void (*windowContent)()) { + virtual void RunUntilWindowClose(void (*windowContent)()) + { while (!glfwWindowShouldClose(mWindow)) { glfwPollEvents(); @@ -76,12 +80,14 @@ public: } } - static void GlfwErrorCallback(int errorCode, const char* message) { + static void GlfwErrorCallback(int errorCode, const char* message) + { std::cerr << "GLFW Error " << errorCode << ": " << message << "\n"; } }; -std::unique_ptr<RenderingBackend> RenderingBackend::CreateOpenGL2Backend() { +std::unique_ptr<RenderingBackend> RenderingBackend::CreateOpenGL2Backend() +{ try { return std::make_unique<OpenGL2Backend>(); } catch (std::exception& e) { @@ -91,7 +97,8 @@ std::unique_ptr<RenderingBackend> RenderingBackend::CreateOpenGL2Backend() { #else // ^^ BUILD_CORE_WITH_OPENGL2_BACKEND | !BUILD_CORE_WITH_OPENGL2_BACKEND vv -std::unique_ptr<RenderingBackend> RenderingBackend::CreateOpenGL2Backend(){}() { +std::unique_ptr<RenderingBackend> RenderingBackend::CreateOpenGL2Backend(){}() +{ return nullptr; } diff --git a/core/src/Entrypoint/Backend_OpenGL3.cpp b/core/src/Entrypoint/Backend_OpenGL3.cpp index 36a0cb3..50dc78f 100644 --- a/core/src/Entrypoint/Backend_OpenGL3.cpp +++ b/core/src/Entrypoint/Backend_OpenGL3.cpp @@ -12,12 +12,14 @@ # define IMGUI_IMPL_OPENGL_LOADER_GLAD # include <backend/imgui_impl_opengl3.cpp> -class OpenGL3Backend : public RenderingBackend { +class OpenGL3Backend : public RenderingBackend +{ private: GLFWwindow* mWindow; public: - OpenGL3Backend() { + OpenGL3Backend() + { glfwSetErrorCallback(&GlfwErrorCallback); if (!glfwInit()) { throw std::runtime_error("Failed to initialize GLFW."); @@ -57,7 +59,8 @@ public: ImGui_ImplOpenGL3_Init(glslVersion); } - virtual ~OpenGL3Backend() { + virtual ~OpenGL3Backend() + { ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); @@ -66,7 +69,8 @@ public: glfwTerminate(); } - virtual void RunUntilWindowClose(void (*windowContent)()) { + virtual void RunUntilWindowClose(void (*windowContent)()) + { while (!glfwWindowShouldClose(mWindow)) { glfwPollEvents(); @@ -91,12 +95,14 @@ public: } } - static void GlfwErrorCallback(int errorCode, const char* message) { + static void GlfwErrorCallback(int errorCode, const char* message) + { std::cerr << "GLFW Error " << errorCode << ": " << message << "\n"; } }; -std::unique_ptr<RenderingBackend> RenderingBackend::CreateOpenGL3Backend() { +std::unique_ptr<RenderingBackend> RenderingBackend::CreateOpenGL3Backend() +{ try { return std::make_unique<OpenGL3Backend>(); } catch (std::exception& e) { @@ -106,7 +112,8 @@ std::unique_ptr<RenderingBackend> RenderingBackend::CreateOpenGL3Backend() { #else // ^^ BUILD_CORE_WITH_OPENGL3_BACKEND | !BUILD_CORE_WITH_OPENGL3_BACKEND vv -std::unique_ptr<RenderingBackend> RenderingBackend::CreateOpenGL3Backend() { +std::unique_ptr<RenderingBackend> RenderingBackend::CreateOpenGL3Backend() +{ return nullptr; } diff --git a/core/src/Entrypoint/Backend_Vulkan.cpp b/core/src/Entrypoint/Backend_Vulkan.cpp index 9d79acf..de3b5ca 100644 --- a/core/src/Entrypoint/Backend_Vulkan.cpp +++ b/core/src/Entrypoint/Backend_Vulkan.cpp @@ -12,7 +12,8 @@ # include <backend/imgui_impl_vulkan.h> # include <backend/imgui_impl_vulkan.cpp> -class VulkanBackend : public RenderingBackend { +class VulkanBackend : public RenderingBackend +{ private: GLFWwindow* mWindow; @@ -31,7 +32,8 @@ private: bool mSwapChainRebuild = false; public: - VulkanBackend() { + VulkanBackend() + { glfwSetErrorCallback(&GlfwErrorCallback); if (!glfwInit()) { throw std::runtime_error("Failed to initialize GLFW."); @@ -80,7 +82,8 @@ public: ImGui_ImplVulkan_Init(&init_info, mMainWindowData.RenderPass); } - virtual ~VulkanBackend() { + virtual ~VulkanBackend() + { auto err = vkDeviceWaitIdle(mDevice); CheckVkResults(err); ImGui_ImplVulkan_Shutdown(); @@ -94,7 +97,8 @@ public: glfwTerminate(); } - virtual void RunUntilWindowClose(void (*windowContent)()) override { + virtual void RunUntilWindowClose(void (*windowContent)()) override + { // Upload Fonts { // Use any command queue @@ -158,7 +162,8 @@ public: } private: - void SetupVulkan(const char** extensions, uint32_t extensions_count) { + void SetupVulkan(const char** extensions, uint32_t extensions_count) + { VkResult err; // Create Vulkan Instance @@ -267,7 +272,8 @@ private: } } - void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height) { + void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height) + { wd->Surface = surface; // Check for WSI support @@ -291,7 +297,8 @@ private: ImGui_ImplVulkanH_CreateOrResizeWindow(mInstance, mPhysicalDevice, mDevice, wd, mQueueFamily, mAllocator, width, height, mMinImageCount); } - void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* drawData) { + void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* drawData) + { VkResult err; VkSemaphore imageAcquiredSemaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore; @@ -356,7 +363,8 @@ private: } } - void FramePresent(ImGui_ImplVulkanH_Window* wd) { + void FramePresent(ImGui_ImplVulkanH_Window* wd) + { if (mSwapChainRebuild) { return; } @@ -378,18 +386,21 @@ private: wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores } - void CleanupVulkan() { + void CleanupVulkan() + { vkDestroyDescriptorPool(mDevice, mDescriptorPool, mAllocator); vkDestroyDevice(mDevice, mAllocator); vkDestroyInstance(mInstance, mAllocator); } - void CleanupVulkanWindow() { + void CleanupVulkanWindow() + { ImGui_ImplVulkanH_DestroyWindow(mInstance, mDevice, &mMainWindowData, mAllocator); } - static void CheckVkResults(VkResult err) { + static void CheckVkResults(VkResult err) + { if (err == 0) return; std::string message; @@ -402,12 +413,14 @@ private: std::cerr << message << '\n'; } } - static void GlfwErrorCallback(int errorCode, const char* message) { + static void GlfwErrorCallback(int errorCode, const char* message) + { std::cerr << "GLFW Error " << errorCode << ": " << message << "\n"; } }; -std::unique_ptr<RenderingBackend> RenderingBackend::CreateVulkanBackend() { +std::unique_ptr<RenderingBackend> RenderingBackend::CreateVulkanBackend() +{ try { return std::make_unique<VulkanBackend>(); } catch (std::exception& e) { @@ -417,7 +430,8 @@ std::unique_ptr<RenderingBackend> RenderingBackend::CreateVulkanBackend() { #else // ^^ BUILD_CORE_WITH_VULKAN_BACKEND | ~BUILD_CORE_WITH_VULKAN_BACKEND vv -std::unique_ptr<RenderingBackend> RenderingBackend::CreateVulkanBackend() { +std::unique_ptr<RenderingBackend> RenderingBackend::CreateVulkanBackend() +{ return nullptr; } diff --git a/core/src/Entrypoint/main.cpp b/core/src/Entrypoint/main.cpp index 8f9832c..2d0238e 100644 --- a/core/src/Entrypoint/main.cpp +++ b/core/src/Entrypoint/main.cpp @@ -21,7 +21,8 @@ namespace fs = std::filesystem; using namespace std::literals::string_literals; using namespace std::literals::string_view_literals; -static std::unique_ptr<RenderingBackend> CreateDefaultBackend() { +static std::unique_ptr<RenderingBackend> CreateDefaultBackend() +{ #if PLATFORM_WIN32 # if BUILD_CORE_WITH_DX12_BACKEND if (auto backend = RenderingBackend::CreateDx12Backend()) { @@ -72,7 +73,8 @@ static std::unique_ptr<RenderingBackend> CreateDefaultBackend() { return nullptr; } -static std::unique_ptr<RenderingBackend> CreateBackend(std::string_view option) { +static std::unique_ptr<RenderingBackend> CreateBackend(std::string_view option) +{ if (option == "default") { return CreateDefaultBackend(); } else if (option == "opengl2") { @@ -96,7 +98,8 @@ static std::unique_ptr<RenderingBackend> CreateBackend(std::string_view option) } } -int main(int argc, char* argv[]) { +int main(int argc, char* argv[]) +{ argparse::ArgumentParser parser; parser.add_argument("--global-data-directory") .help("Directory in which global data (such as recently used projects) are saved to. Use 'default' to use the default directory on each platform.") @@ -159,10 +162,16 @@ int main(int argc, char* argv[]) { GlobalStates::Init(); } } - DEFER { GlobalStates::Shutdown(); }; + DEFER + { + GlobalStates::Shutdown(); + }; UIState::Init(); - DEFER { UIState::Shutdown(); }; + DEFER + { + UIState::Shutdown(); + }; // Main loop backend->RunUntilWindowClose(&UI::MainWindow); diff --git a/core/src/Model/Filter.hpp b/core/src/Model/Filter.hpp index 53995c1..1b923e1 100644 --- a/core/src/Model/Filter.hpp +++ b/core/src/Model/Filter.hpp @@ -1,5 +1,6 @@ #pragma once -class TableRowsFilter { +class TableRowsFilter +{ // TODO }; diff --git a/core/src/Model/GlobalStates.cpp b/core/src/Model/GlobalStates.cpp index 0c4e58e..4004f4a 100644 --- a/core/src/Model/GlobalStates.cpp +++ b/core/src/Model/GlobalStates.cpp @@ -16,11 +16,13 @@ namespace fs = std::filesystem; static std::unique_ptr<GlobalStates> globalStateInstance; static fs::path globalDataPath; -void GlobalStates::Init() { +void GlobalStates::Init() +{ Init(StandardDirectories::UserData() / "cplt"); } -void GlobalStates::Init(std::filesystem::path userDataDir) { +void GlobalStates::Init(std::filesystem::path userDataDir) +{ globalStateInstance = std::make_unique<GlobalStates>(); globalDataPath = userDataDir; fs::create_directories(globalDataPath); @@ -51,31 +53,37 @@ void GlobalStates::Init(std::filesystem::path userDataDir) { }(); } -void GlobalStates::Shutdown() { +void GlobalStates::Shutdown() +{ if (!globalStateInstance) return; if (globalStateInstance->mDirty) { globalStateInstance->WriteToDisk(); } } -GlobalStates& GlobalStates::GetInstance() { +GlobalStates& GlobalStates::GetInstance() +{ return *globalStateInstance; } -const std::filesystem::path& GlobalStates::GetUserDataPath() { +const std::filesystem::path& GlobalStates::GetUserDataPath() +{ return globalDataPath; } -const std::vector<GlobalStates::RecentProject>& GlobalStates::GetRecentProjects() const { +const std::vector<GlobalStates::RecentProject>& GlobalStates::GetRecentProjects() const +{ return mRecentProjects; } -void GlobalStates::ClearRecentProjects() { +void GlobalStates::ClearRecentProjects() +{ mRecentProjects.clear(); MarkDirty(); } -void GlobalStates::AddRecentProject(const Project& project) { +void GlobalStates::AddRecentProject(const Project& project) +{ mRecentProjects.push_back(RecentProject{ .path = project.GetPath(), .cachedUtf8String = project.GetPath().string(), @@ -83,7 +91,8 @@ void GlobalStates::AddRecentProject(const Project& project) { MarkDirty(); } -void GlobalStates::MoveProjectToTop(const Project& project) { +void GlobalStates::MoveProjectToTop(const Project& project) +{ for (auto it = mRecentProjects.begin(); it != mRecentProjects.end(); ++it) { if (it->path == project.GetPath()) { std::rotate(it, it + 1, mRecentProjects.end()); @@ -94,14 +103,16 @@ void GlobalStates::MoveProjectToTop(const Project& project) { AddRecentProject(project); } -void GlobalStates::RemoveRecentProject(int idx) { +void GlobalStates::RemoveRecentProject(int idx) +{ assert(idx >= 0 && idx < mRecentProjects.size()); mRecentProjects.erase(mRecentProjects.begin() + idx); MarkDirty(); } -void GlobalStates::WriteToDisk() const { +void GlobalStates::WriteToDisk() const +{ Json::Value root; auto& recentProjects = root["RecentProjects"] = Json::Value(Json::arrayValue); @@ -115,11 +126,13 @@ void GlobalStates::WriteToDisk() const { mDirty = false; } -bool GlobalStates::IsDirty() const { +bool GlobalStates::IsDirty() const +{ return mDirty; } -void GlobalStates::MarkDirty() { +void GlobalStates::MarkDirty() +{ mDirty = true; OnModified(); } diff --git a/core/src/Model/GlobalStates.hpp b/core/src/Model/GlobalStates.hpp index 8375569..d88f752 100644 --- a/core/src/Model/GlobalStates.hpp +++ b/core/src/Model/GlobalStates.hpp @@ -7,7 +7,8 @@ #include <string> #include <vector> -class GlobalStates { +class GlobalStates +{ public: static void Init(); static void Init(std::filesystem::path userDataDir); @@ -16,7 +17,8 @@ public: static GlobalStates& GetInstance(); static const std::filesystem::path& GetUserDataPath(); - struct RecentProject { + struct RecentProject + { std::filesystem::path path; std::string cachedUtf8String; }; diff --git a/core/src/Model/Items.cpp b/core/src/Model/Items.cpp index 02a4516..9d2abc6 100644 --- a/core/src/Model/Items.cpp +++ b/core/src/Model/Items.cpp @@ -1,29 +1,36 @@ #include "Items.hpp" -const std::string& ProductItem::GetDescription() const { +const std::string& ProductItem::GetDescription() const +{ return mDescription; } -void ProductItem::SetDescription(std::string description) { +void ProductItem::SetDescription(std::string description) +{ mDescription = std::move(description); } -int ProductItem::GetPrice() const { +int ProductItem::GetPrice() const +{ return mPrice; } -void ProductItem::SetPrice(int price) { +void ProductItem::SetPrice(int price) +{ mPrice = price; } -int ProductItem::GetStock() const { +int ProductItem::GetStock() const +{ return mStock; } -void ProductItem::SetStock(int stock) { +void ProductItem::SetStock(int stock) +{ mStock = stock; } -Json::Value ProductItem::Serialize() const { +Json::Value ProductItem::Serialize() const +{ Json::Value elm; elm["Description"] = mDescription; elm["Price"] = mPrice; @@ -31,64 +38,77 @@ Json::Value ProductItem::Serialize() const { return elm; } -void ProductItem::Deserialize(const Json::Value& elm) { +void ProductItem::Deserialize(const Json::Value& elm) +{ mDescription = elm["Description"].asString(); mPrice = elm["Price"].asInt(); mStock = elm["Stock"].asInt(); } -const std::string& FactoryItem::GetDescription() const { +const std::string& FactoryItem::GetDescription() const +{ return mDescription; } -void FactoryItem::SetDescription(std::string description) { +void FactoryItem::SetDescription(std::string description) +{ mDescription = std::move(description); } -const std::string& FactoryItem::GetEmail() const { +const std::string& FactoryItem::GetEmail() const +{ return mEmail; } -void FactoryItem::SetEmail(std::string email) { +void FactoryItem::SetEmail(std::string email) +{ mEmail = std::move(email); } -Json::Value FactoryItem::Serialize() const { +Json::Value FactoryItem::Serialize() const +{ Json::Value elm; elm["Description"] = mDescription; elm["Email"] = mEmail; return elm; } -void FactoryItem::Deserialize(const Json::Value& elm) { +void FactoryItem::Deserialize(const Json::Value& elm) +{ mDescription = elm["Description"].asString(); mEmail = elm["Email"].asString(); } -const std::string& CustomerItem::GetDescription() const { +const std::string& CustomerItem::GetDescription() const +{ return mDescription; } -void CustomerItem::SetDescription(std::string description) { +void CustomerItem::SetDescription(std::string description) +{ mDescription = std::move(description); } -const std::string& CustomerItem::GetEmail() const { +const std::string& CustomerItem::GetEmail() const +{ return mEmail; } -void CustomerItem::SetEmail(std::string email) { +void CustomerItem::SetEmail(std::string email) +{ mEmail = std::move(email); } -Json::Value CustomerItem::Serialize() const { +Json::Value CustomerItem::Serialize() const +{ Json::Value elm; elm["Description"] = mDescription; elm["Email"] = mEmail; return elm; } -void CustomerItem::Deserialize(const Json::Value& elm) { +void CustomerItem::Deserialize(const Json::Value& elm) +{ mDescription = elm["Description"].asString(); mEmail = elm["Email"].asString(); } diff --git a/core/src/Model/Items.hpp b/core/src/Model/Items.hpp index 1289be6..859aedf 100644 --- a/core/src/Model/Items.hpp +++ b/core/src/Model/Items.hpp @@ -15,14 +15,16 @@ #include <vector> template <class T> -class ItemList { +class ItemList +{ private: std::vector<T> mStorage; tsl::array_map<char, size_t> mNameLookup; public: template <class... Args> - T& Insert(std::string name, Args... args) { + T& Insert(std::string name, Args... args) + { auto iter = mNameLookup.find(name); if (iter != mNameLookup.end()) { throw std::runtime_error("Duplicate key."); @@ -42,21 +44,25 @@ public: return mStorage[id]; } - void Remove(size_t index) { + void Remove(size_t index) + { auto& item = mStorage[index]; mNameLookup.erase(item.GetName()); mStorage[index] = T(*this); } - T* Find(size_t id) { + T* Find(size_t id) + { return &mStorage[id]; } - const T* Find(size_t id) const { + const T* Find(size_t id) const + { return &mStorage[id]; } - const T* Find(std::string_view name) const { + const T* Find(std::string_view name) const + { auto iter = mNameLookup.find(name); if (iter != mNameLookup.end()) { return &mStorage[iter.value()]; @@ -65,7 +71,8 @@ public: } } - Json::Value Serialize() const { + Json::Value Serialize() const + { Json::Value items(Json::arrayValue); for (auto& item : mStorage) { if (!item.IsInvalid()) { @@ -85,7 +92,8 @@ public: ItemList() = default; - ItemList(const Json::Value& root) { + ItemList(const Json::Value& root) + { constexpr const char* kMessage = "Failed to load item list from JSON."; auto& itemCount = root["MaxItemId"]; @@ -110,19 +118,23 @@ public: } } - typename decltype(mStorage)::iterator begin() { + typename decltype(mStorage)::iterator begin() + { return mStorage.begin(); } - typename decltype(mStorage)::iterator end() { + typename decltype(mStorage)::iterator end() + { return mStorage.end(); } - typename decltype(mStorage)::const_iterator begin() const { + typename decltype(mStorage)::const_iterator begin() const + { return mStorage.begin(); } - typename decltype(mStorage)::const_iterator end() const { + typename decltype(mStorage)::const_iterator end() const + { return mStorage.end(); } @@ -130,14 +142,16 @@ private: template <class TSelf> friend class ItemBase; - void UpdateItemName(const T& item, const std::string& newName) { + void UpdateItemName(const T& item, const std::string& newName) + { mNameLookup.erase(item.GetName()); mNameLookup.insert(newName, item.GetId()); } }; template <class TSelf> -class ItemBase { +class ItemBase +{ private: ItemList<TSelf>* mList; size_t mId; @@ -147,32 +161,39 @@ public: ItemBase(ItemList<TSelf>& list, size_t id = std::numeric_limits<size_t>::max(), std::string name = "") : mList{ &list } , mId{ id } - , mName{ std::move(name) } { + , mName{ std::move(name) } + { } - bool IsInvalid() const { + bool IsInvalid() const + { return mId == std::numeric_limits<size_t>::max(); } - ItemList<TSelf>& GetList() const { + ItemList<TSelf>& GetList() const + { return *mList; } - size_t GetId() const { + size_t GetId() const + { return mId; } - const std::string& GetName() const { + const std::string& GetName() const + { return mName; } - void SetName(std::string name) { + void SetName(std::string name) + { mList->UpdateItemName(static_cast<TSelf&>(*this), name); mName = std::move(name); } }; -class ProductItem : public ItemBase<ProductItem> { +class ProductItem : public ItemBase<ProductItem> +{ private: std::string mDescription; int mPrice = 0; @@ -195,7 +216,8 @@ public: void Deserialize(const Json::Value& elm); }; -class FactoryItem : public ItemBase<FactoryItem> { +class FactoryItem : public ItemBase<FactoryItem> +{ private: std::string mDescription; std::string mEmail; @@ -212,7 +234,8 @@ public: void Deserialize(const Json::Value& elm); }; -class CustomerItem : public ItemBase<CustomerItem> { +class CustomerItem : public ItemBase<CustomerItem> +{ private: std::string mDescription; std::string mEmail; diff --git a/core/src/Model/Project.cpp b/core/src/Model/Project.cpp index e762efb..74e7142 100644 --- a/core/src/Model/Project.cpp +++ b/core/src/Model/Project.cpp @@ -11,7 +11,8 @@ namespace fs = std::filesystem; template <class T> -void ReadItemList(ItemList<T>& list, const fs::path& filePath) { +void ReadItemList(ItemList<T>& list, const fs::path& filePath) +{ std::ifstream ifs(filePath); if (ifs) { Json::Value root; @@ -24,7 +25,8 @@ void ReadItemList(ItemList<T>& list, const fs::path& filePath) { Project::Project(const fs::path& rootPath) : mRootPath{ rootPath } , mRootPathString{ mRootPath.string() } - , mDb(*this) { + , mDb(*this) +{ // TODO better diagnostic const char* kInvalidFormatErr = "Failed to load project: invalid format."; @@ -63,34 +65,42 @@ Project::Project(std::filesystem::path rootPath, std::string name) : mRootPath{ std::move(rootPath) } , mRootPathString{ mRootPath.string() } , mName{ std::move(name) } - , mDb(*this) { + , mDb(*this) +{ } -const fs::path& Project::GetPath() const { +const fs::path& Project::GetPath() const +{ return mRootPath; } -const std::string& Project::GetPathString() const { +const std::string& Project::GetPathString() const +{ return mRootPathString; } -const std::string& Project::GetName() const { +const std::string& Project::GetName() const +{ return mName; } -void Project::SetName(std::string name) { +void Project::SetName(std::string name) +{ mName = std::move(name); } -const TransactionModel& Project::GetTransactionsModel() const { +const TransactionModel& Project::GetTransactionsModel() const +{ return mDb; } -TransactionModel& Project::GetTransactionsModel() { +TransactionModel& Project::GetTransactionsModel() +{ return mDb; } -Json::Value Project::Serialize() { +Json::Value Project::Serialize() +{ Json::Value root(Json::objectValue); root["Name"] = mName; @@ -99,12 +109,14 @@ Json::Value Project::Serialize() { } template <class T> -static void WriteItemList(ItemList<T>& list, const fs::path& filePath) { +static void WriteItemList(ItemList<T>& list, const fs::path& filePath) +{ std::ofstream ofs(filePath); ofs << list.Serialize(); } -void Project::WriteToDisk() { +void Project::WriteToDisk() +{ std::ofstream ofs(mRootPath / "cplt_project.json"); ofs << this->Serialize(); diff --git a/core/src/Model/Project.hpp b/core/src/Model/Project.hpp index 748ca82..998befb 100644 --- a/core/src/Model/Project.hpp +++ b/core/src/Model/Project.hpp @@ -7,7 +7,8 @@ #include <filesystem> #include <string> -class Project { +class Project +{ public: ItemList<ProductItem> Products; ItemList<FactoryItem> Factories; diff --git a/core/src/Model/TransactionsModel.cpp b/core/src/Model/TransactionsModel.cpp index 914191d..6d0989e 100644 --- a/core/src/Model/TransactionsModel.cpp +++ b/core/src/Model/TransactionsModel.cpp @@ -9,26 +9,28 @@ namespace fs = std::filesystem; SalesTable::SalesTable(TransactionModel& db) // language=SQLite - : GetRowCountStatement(db.GetSQLite(), "SELECT Count(*) FROM Sales") + : GetRowCount(db.GetSQLite(), "SELECT Count(*) FROM Sales") // language=SQLite - , GetRowsStatement(db.GetSQLite(), "SELECT * FROM Sales WHERE rowid >= ? AND rowid < ?") - // language=SQLite - // TODO - , FilterRowsStatement(db.GetSQLite(), R"""( -)""") { + , GetRows(db.GetSQLite(), "SELECT * FROM Sales WHERE rowid >= ? AND rowid < ?") +{ } PurchasesTable::PurchasesTable(TransactionModel& db) // language=SQLite - : GetRowCountStatement(db.GetSQLite(), "SELECT Count(*) FROM Purchases") + : GetRowCount(db.GetSQLite(), "SELECT Count(*) FROM Purchases") // language=SQLite - , GetRowsStatement(db.GetSQLite(), "SELECT * FROM Purchases WHERE rowid >= ? AND rowid < ?") { + , GetRows(db.GetSQLite(), "SELECT * FROM Purchases WHERE rowid >= ? AND rowid < ?") +{ } -DeliveryTable::DeliveryTable(TransactionModel& db) { +DeliveryTable::DeliveryTable(TransactionModel& db) + // language=SQLite + : FilterByTypeAndId(db.GetSQLite(), "SELECT * FROM Deliveries WHERE AssociatedOrder == ? AND Outgoing = ?") +{ } -static std::string GetDatabaseFilePath(const Project& project) { +static std::string GetDatabaseFilePath(const Project& project) +{ auto dbsDir = project.GetPath() / "databases"; fs::create_directories(dbsDir); @@ -38,8 +40,8 @@ static std::string GetDatabaseFilePath(const Project& project) { /// Wrapper for SQLite::Database that creates the default tables TransactionModel::DatabaseWrapper::DatabaseWrapper(TransactionModel& self) - : mSqlite(GetDatabaseFilePath(*self.mProject), SQLite::OPEN_READWRITE) { - + : mSqlite(GetDatabaseFilePath(*self.mProject), SQLite::OPEN_READWRITE) +{ // If this table doesn't exist, the database probably just got initialized if (mSqlite.tableExists("Sales")) { return; @@ -56,8 +58,8 @@ TransactionModel::DatabaseWrapper::DatabaseWrapper(TransactionModel& self) // - DeliveryTime: the time this order was completed (through a set of deliveries) // 'Deliveries' schema - // - SendTime: unix epoch time of sending to delivery - // - ArriveTime: unix epoch time of delivery arrived at warehouse; 0 if not arrived yet + // - ShipmentTime: unix epoch time of sending to delivery + // - ArrivalTime: unix epoch time of delivery arrived at warehouse; 0 if not arrived yet // - AssociatedOrder: rowid of the order that this delivery is completing (which table: Outgoing=true -> Sales, Outgoing=false -> Purchases) // - Outgoing: true if the delivery is from warehouse to customer; false if the delivery is from factory to warehouse @@ -76,28 +78,28 @@ CREATE TABLE IF NOT EXISTS SalesItems( ); CREATE TABLE IF NOT EXISTS Purchases( - INT PRIMARY KEY, - Factory INT, - OrderTime DATETIME, - DeliveryTime DATETIME + INT PRIMARY KEY, + Factory INT, + OrderTime DATETIME, + DeliveryTime DATETIME ); CREATE TABLE IF NOT EXISTS PurchasesItems( - PurchaseId INT, - ItemId INT, - Count INT + PurchaseId INT, + ItemId INT, + Count INT ); CREATE TABLE IF NOT EXISTS Deliveries( - INT PRIMARY KEY, - SendTime DATETIME, - ArriveTime DATETIME, - AssociatedOrder INT, - Outgoing BOOLEAN + INT PRIMARY KEY, + ShipmentTime DATETIME, + ArrivalTime DATETIME, + AssociatedOrder INT, + Outgoing BOOLEAN ); CREATE TABLE IF NOT EXISTS DeliveriesItems( - DeliveryId INT, - ItemId INT, - Count INT + DeliveryId INT, + ItemId INT, + Count INT ); )"""); } @@ -107,37 +109,46 @@ TransactionModel::TransactionModel(Project& project) , mDbWrapper(*this) , mSales(*this) , mPurchases(*this) - , mDeliveries(*this) { + , mDeliveries(*this) +{ } -const SQLite::Database& TransactionModel::GetSQLite() const { +const SQLite::Database& TransactionModel::GetSQLite() const +{ return mDbWrapper.mSqlite; } -SQLite::Database& TransactionModel::GetSQLite() { +SQLite::Database& TransactionModel::GetSQLite() +{ return mDbWrapper.mSqlite; } -const SalesTable& TransactionModel::GetSales() const { +const SalesTable& TransactionModel::GetSales() const +{ return mSales; } -SalesTable& TransactionModel::GetSales() { +SalesTable& TransactionModel::GetSales() +{ return mSales; } -const PurchasesTable& TransactionModel::GetPurchases() const { +const PurchasesTable& TransactionModel::GetPurchases() const +{ return mPurchases; } -PurchasesTable& TransactionModel::GetPurchases() { +PurchasesTable& TransactionModel::GetPurchases() +{ return mPurchases; } -const DeliveryTable& TransactionModel::GetDeliveries() const { +const DeliveryTable& TransactionModel::GetDeliveries() const +{ return mDeliveries; } -DeliveryTable& TransactionModel::GetDeliveries() { +DeliveryTable& TransactionModel::GetDeliveries() +{ return mDeliveries; } diff --git a/core/src/Model/TransactionsModel.hpp b/core/src/Model/TransactionsModel.hpp index 7a71fca..86611cf 100644 --- a/core/src/Model/TransactionsModel.hpp +++ b/core/src/Model/TransactionsModel.hpp @@ -6,34 +6,41 @@ #include <SQLiteCpp/Statement.h> #include <cstdint> -class SalesTable { +class SalesTable +{ public: - SQLite::Statement GetRowCountStatement; - SQLite::Statement GetRowsStatement; - SQLite::Statement FilterRowsStatement; + SQLite::Statement GetRowCount; + SQLite::Statement GetRows; public: SalesTable(TransactionModel& db); }; -class PurchasesTable { +class PurchasesTable +{ public: - SQLite::Statement GetRowCountStatement; - SQLite::Statement GetRowsStatement; + SQLite::Statement GetRowCount; + SQLite::Statement GetRows; public: PurchasesTable(TransactionModel& db); }; -class DeliveryTable { +class DeliveryTable +{ +public: + SQLite::Statement FilterByTypeAndId; + public: DeliveryTable(TransactionModel& db); }; // TODO fuck SQLite::Statement has move ctor but not move assignment operator -class TransactionModel { +class TransactionModel +{ private: - class DatabaseWrapper { + class DatabaseWrapper + { public: SQLite::Database mSqlite; DatabaseWrapper(TransactionModel& self); diff --git a/core/src/Model/Workflow/Evaluation.cpp b/core/src/Model/Workflow/Evaluation.cpp index ff3edf4..f6472dd 100644 --- a/core/src/Model/Workflow/Evaluation.cpp +++ b/core/src/Model/Workflow/Evaluation.cpp @@ -2,14 +2,16 @@ #include <queue> -const char* WorkflowEvaluationError::FormatMessageType(enum MessageType messageType) { +const char* WorkflowEvaluationError::FormatMessageType(enum MessageType messageType) +{ switch (messageType) { case Error: return "Error"; case Warning: return "Warning"; } } -const char* WorkflowEvaluationError::FormatPinType(enum PinType pinType) { +const char* WorkflowEvaluationError::FormatPinType(enum PinType pinType) +{ switch (pinType) { case NoPin: return nullptr; case InputPin: return "Input pin"; @@ -17,7 +19,8 @@ const char* WorkflowEvaluationError::FormatPinType(enum PinType pinType) { } } -std::string WorkflowEvaluationError::Format() const { +std::string WorkflowEvaluationError::Format() const +{ // TODO convert to std::format std::string result; @@ -37,32 +40,38 @@ std::string WorkflowEvaluationError::Format() const { } namespace { -enum class EvaluationStatus { +enum class EvaluationStatus +{ Unevaluated, Success, Failed, }; } // namespace -struct WorkflowEvaluationContext::RuntimeNode { +struct WorkflowEvaluationContext::RuntimeNode +{ EvaluationStatus Status = EvaluationStatus::Unevaluated; }; -struct WorkflowEvaluationContext::RuntimeConnection { +struct WorkflowEvaluationContext::RuntimeConnection +{ std::unique_ptr<BaseValue> Value; - bool IsAvailableValue() const { + bool IsAvailableValue() const + { return Value != nullptr; } }; WorkflowEvaluationContext::WorkflowEvaluationContext(Workflow& workflow) - : mWorkflow{ &workflow } { + : mWorkflow{ &workflow } +{ mRuntimeNodes.resize(workflow.mNodes.size()); mRuntimeConnections.resize(workflow.mConnections.size()); } -BaseValue* WorkflowEvaluationContext::GetConnectionValue(size_t id, bool constant) { +BaseValue* WorkflowEvaluationContext::GetConnectionValue(size_t id, bool constant) +{ if (constant) { return mWorkflow->GetConstantById(id); } else { @@ -70,7 +79,8 @@ BaseValue* WorkflowEvaluationContext::GetConnectionValue(size_t id, bool constan } } -BaseValue* WorkflowEvaluationContext::GetConnectionValue(const WorkflowNode::InputPin& inputPin) { +BaseValue* WorkflowEvaluationContext::GetConnectionValue(const WorkflowNode::InputPin& inputPin) +{ if (inputPin.IsConnected()) { return GetConnectionValue(inputPin.Connection, inputPin.IsConstantConnection()); } else { @@ -78,17 +88,20 @@ BaseValue* WorkflowEvaluationContext::GetConnectionValue(const WorkflowNode::Inp } } -void WorkflowEvaluationContext::SetConnectionValue(size_t id, std::unique_ptr<BaseValue> value) { +void WorkflowEvaluationContext::SetConnectionValue(size_t id, std::unique_ptr<BaseValue> value) +{ mRuntimeConnections[id].Value = std::move(value); } -void WorkflowEvaluationContext::SetConnectionValue(const WorkflowNode::OutputPin& outputPin, std::unique_ptr<BaseValue> value) { +void WorkflowEvaluationContext::SetConnectionValue(const WorkflowNode::OutputPin& outputPin, std::unique_ptr<BaseValue> value) +{ if (outputPin.IsConnected()) { SetConnectionValue(outputPin.Connection, std::move(value)); } } -void WorkflowEvaluationContext::Run() { +void WorkflowEvaluationContext::Run() +{ int evaluatedCount = 0; int erroredCount = 0; @@ -118,7 +131,8 @@ void WorkflowEvaluationContext::Run() { } } -void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowNode& node, int pinId, bool inputPin) { +void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowNode& node, int pinId, bool inputPin) +{ mErrors.push_back(WorkflowEvaluationError{ .Message = std::move(message), .NodeId = node.GetId(), @@ -128,7 +142,8 @@ void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowN }); } -void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowNode& node) { +void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowNode& node) +{ mErrors.push_back(WorkflowEvaluationError{ .Message = std::move(message), .NodeId = node.GetId(), @@ -138,7 +153,8 @@ void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowN }); } -void WorkflowEvaluationContext::ReportWarning(std::string message, const WorkflowNode& node, int pinId, bool inputPin) { +void WorkflowEvaluationContext::ReportWarning(std::string message, const WorkflowNode& node, int pinId, bool inputPin) +{ mErrors.push_back(WorkflowEvaluationError{ .Message = std::move(message), .NodeId = node.GetId(), @@ -148,7 +164,8 @@ void WorkflowEvaluationContext::ReportWarning(std::string message, const Workflo }); } -void WorkflowEvaluationContext::ReportWarning(std::string message, const WorkflowNode& node) { +void WorkflowEvaluationContext::ReportWarning(std::string message, const WorkflowNode& node) +{ mErrors.push_back(WorkflowEvaluationError{ .Message = std::move(message), .NodeId = node.GetId(), diff --git a/core/src/Model/Workflow/Evaluation.hpp b/core/src/Model/Workflow/Evaluation.hpp index d068c45..4d78872 100644 --- a/core/src/Model/Workflow/Evaluation.hpp +++ b/core/src/Model/Workflow/Evaluation.hpp @@ -7,14 +7,17 @@ #include <string> #include <vector> -class WorkflowEvaluationError { +class WorkflowEvaluationError +{ public: - enum MessageType : int16_t { + enum MessageType : int16_t + { Error, Warning, }; - enum PinType : int16_t { + enum PinType : int16_t + { NoPin, InputPin, OutputPin, @@ -34,7 +37,8 @@ public: std::string Format() const; }; -class WorkflowEvaluationContext { +class WorkflowEvaluationContext +{ private: struct RuntimeNode; struct RuntimeConnection; diff --git a/core/src/Model/Workflow/Nodes/DocumentNodes.cpp b/core/src/Model/Workflow/Nodes/DocumentNodes.cpp index 255d446..b858b49 100644 --- a/core/src/Model/Workflow/Nodes/DocumentNodes.cpp +++ b/core/src/Model/Workflow/Nodes/DocumentNodes.cpp @@ -3,13 +3,16 @@ #include "Model/Workflow/Evaluation.hpp" #include "Model/Workflow/Values/BasicValues.hpp" -bool DocumentTemplateExpansionNode::IsInstance(const WorkflowNode* node) { +bool DocumentTemplateExpansionNode::IsInstance(const WorkflowNode* node) +{ return node->GetKind() == KD_DocumentTemplateExpansion; } DocumentTemplateExpansionNode::DocumentTemplateExpansionNode() - : WorkflowNode(KD_DocumentTemplateExpansion) { + : WorkflowNode(KD_DocumentTemplateExpansion) +{ } -void DocumentTemplateExpansionNode::Evaluate(WorkflowEvaluationContext& ctx) { +void DocumentTemplateExpansionNode::Evaluate(WorkflowEvaluationContext& ctx) +{ } diff --git a/core/src/Model/Workflow/Nodes/DocumentNodes.hpp b/core/src/Model/Workflow/Nodes/DocumentNodes.hpp index 3b775ec..85bba9e 100644 --- a/core/src/Model/Workflow/Nodes/DocumentNodes.hpp +++ b/core/src/Model/Workflow/Nodes/DocumentNodes.hpp @@ -2,7 +2,8 @@ #include "Model/Workflow/Workflow.hpp" -class DocumentTemplateExpansionNode : public WorkflowNode { +class DocumentTemplateExpansionNode : public WorkflowNode +{ public: static bool IsInstance(const WorkflowNode* node); DocumentTemplateExpansionNode(); diff --git a/core/src/Model/Workflow/Nodes/NumericNodes.cpp b/core/src/Model/Workflow/Nodes/NumericNodes.cpp index f054421..138b35d 100644 --- a/core/src/Model/Workflow/Nodes/NumericNodes.cpp +++ b/core/src/Model/Workflow/Nodes/NumericNodes.cpp @@ -8,7 +8,8 @@ #include <cassert> #include <utility> -WorkflowNode::Kind NumericOperationNode::OperationTypeToNodeKind(OperationType type) { +WorkflowNode::Kind NumericOperationNode::OperationTypeToNodeKind(OperationType type) +{ switch (type) { case Addition: return KD_NumericAddition; case Subtraction: return KD_NumericSubtraction; @@ -18,7 +19,8 @@ WorkflowNode::Kind NumericOperationNode::OperationTypeToNodeKind(OperationType t } } -NumericOperationNode::OperationType NumericOperationNode::NodeKindToOperationType(Kind kind) { +NumericOperationNode::OperationType NumericOperationNode::NodeKindToOperationType(Kind kind) +{ switch (kind) { case KD_NumericAddition: return Addition; case KD_NumericSubtraction: return Subtraction; @@ -28,13 +30,15 @@ NumericOperationNode::OperationType NumericOperationNode::NodeKindToOperationTyp } } -bool NumericOperationNode::IsInstance(const WorkflowNode* node) { +bool NumericOperationNode::IsInstance(const WorkflowNode* node) +{ return node->GetKind() >= KD_NumericAddition && node->GetKind() <= KD_NumericDivision; } NumericOperationNode::NumericOperationNode(OperationType type) : WorkflowNode(OperationTypeToNodeKind(type)) - , mType{ type } { + , mType{ type } +{ mInputs.resize(2); mInputs[0].MatchingType = BaseValue::KD_Numeric; mInputs[1].MatchingType = BaseValue::KD_Numeric; @@ -43,7 +47,8 @@ NumericOperationNode::NumericOperationNode(OperationType type) mOutputs[0].MatchingType = BaseValue::KD_Numeric; } -void NumericOperationNode::Evaluate(WorkflowEvaluationContext& ctx) { +void NumericOperationNode::Evaluate(WorkflowEvaluationContext& ctx) +{ auto lhsVal = dyn_cast<NumericValue>(ctx.GetConnectionValue(mInputs[0])); if (!lhsVal) return; double lhs = lhsVal->GetValue(); @@ -74,13 +79,16 @@ void NumericOperationNode::Evaluate(WorkflowEvaluationContext& ctx) { ctx.SetConnectionValue(mOutputs[0], std::move(value)); } -bool NumericExpressionNode::IsInstance(const WorkflowNode* node) { +bool NumericExpressionNode::IsInstance(const WorkflowNode* node) +{ return node->GetKind() == KD_NumericExpression; } NumericExpressionNode::NumericExpressionNode() - : WorkflowNode(KD_NumericExpression) { + : WorkflowNode(KD_NumericExpression) +{ } -void NumericExpressionNode::Evaluate(WorkflowEvaluationContext& ctx) { +void NumericExpressionNode::Evaluate(WorkflowEvaluationContext& ctx) +{ } diff --git a/core/src/Model/Workflow/Nodes/NumericNodes.hpp b/core/src/Model/Workflow/Nodes/NumericNodes.hpp index 32610f6..56c0313 100644 --- a/core/src/Model/Workflow/Nodes/NumericNodes.hpp +++ b/core/src/Model/Workflow/Nodes/NumericNodes.hpp @@ -7,9 +7,11 @@ #include <variant> #include <vector> -class NumericOperationNode : public WorkflowNode { +class NumericOperationNode : public WorkflowNode +{ public: - enum OperationType { + enum OperationType + { Addition, Subtraction, Multiplication, @@ -31,7 +33,8 @@ public: virtual void Evaluate(WorkflowEvaluationContext& ctx) override; }; -class NumericExpressionNode : public WorkflowNode { +class NumericExpressionNode : public WorkflowNode +{ public: static bool IsInstance(const WorkflowNode* node); NumericExpressionNode(); diff --git a/core/src/Model/Workflow/Nodes/TextNodes.cpp b/core/src/Model/Workflow/Nodes/TextNodes.cpp index 72bd666..944fc07 100644 --- a/core/src/Model/Workflow/Nodes/TextNodes.cpp +++ b/core/src/Model/Workflow/Nodes/TextNodes.cpp @@ -11,10 +11,12 @@ #include <variant> #include <vector> -class TextFormatterNode::Impl { +class TextFormatterNode::Impl +{ public: template <class TFunction> - static void ForArguments(std::vector<Element>::iterator begin, std::vector<Element>::iterator end, const TFunction& func) { + static void ForArguments(std::vector<Element>::iterator begin, std::vector<Element>::iterator end, const TFunction& func) + { for (auto it = begin; it != end; ++it) { auto& elm = *it; if (auto arg = std::get_if<Argument>(&elm)) { @@ -24,7 +26,8 @@ public: } /// Find the pin index that the \c elmIdx -th element should have, based on the elements coming before it. - static int FindPinForElement(const std::vector<Element>& vec, int elmIdx) { + static int FindPinForElement(const std::vector<Element>& vec, int elmIdx) + { for (int i = elmIdx; i >= 0; --i) { auto& elm = vec[i]; if (auto arg = std::get_if<Argument>(&elm)) { @@ -35,7 +38,8 @@ public: } }; -BaseValue::Kind TextFormatterNode::ArgumentTypeToValueKind(TextFormatterNode::ArgumentType arg) { +BaseValue::Kind TextFormatterNode::ArgumentTypeToValueKind(TextFormatterNode::ArgumentType arg) +{ switch (arg) { case NumericArgument: return BaseValue::KD_Numeric; case TextArgument: return BaseValue::KD_Text; @@ -44,23 +48,28 @@ BaseValue::Kind TextFormatterNode::ArgumentTypeToValueKind(TextFormatterNode::Ar } } -bool TextFormatterNode::IsInstance(const WorkflowNode* node) { +bool TextFormatterNode::IsInstance(const WorkflowNode* node) +{ return node->GetKind() == KD_TextFormatting; } TextFormatterNode::TextFormatterNode() - : WorkflowNode(KD_TextFormatting) { + : WorkflowNode(KD_TextFormatting) +{ } -int TextFormatterNode::GetElementCount() const { +int TextFormatterNode::GetElementCount() const +{ return mElements.size(); } -const TextFormatterNode::Element& TextFormatterNode::GetElement(int idx) const { +const TextFormatterNode::Element& TextFormatterNode::GetElement(int idx) const +{ return mElements[idx]; } -void TextFormatterNode::SetElement(int idx, std::string text) { +void TextFormatterNode::SetElement(int idx, std::string text) +{ assert(idx >= 0 && idx < mElements.size()); std::visit( @@ -74,7 +83,8 @@ void TextFormatterNode::SetElement(int idx, std::string text) { mElements[idx] = std::move(text); } -void TextFormatterNode::SetElement(int idx, ArgumentType argument) { +void TextFormatterNode::SetElement(int idx, ArgumentType argument) +{ assert(idx >= 0 && idx < mElements.size()); std::visit( @@ -106,7 +116,8 @@ void TextFormatterNode::SetElement(int idx, ArgumentType argument) { mElements[idx]); } -void TextFormatterNode::InsertElement(int idx, std::string text) { +void TextFormatterNode::InsertElement(int idx, std::string text) +{ assert(idx >= 0); if (idx >= mElements.size()) AppendElement(std::move(text)); @@ -114,7 +125,8 @@ void TextFormatterNode::InsertElement(int idx, std::string text) { mElements.insert(mElements.begin() + idx, std::move(text)); } -void TextFormatterNode::InsertElement(int idx, ArgumentType argument) { +void TextFormatterNode::InsertElement(int idx, ArgumentType argument) +{ assert(idx >= 0); if (idx >= mElements.size()) AppendElement(argument); @@ -133,12 +145,14 @@ void TextFormatterNode::InsertElement(int idx, ArgumentType argument) { }); } -void TextFormatterNode::AppendElement(std::string text) { +void TextFormatterNode::AppendElement(std::string text) +{ mMinOutputChars += text.size(); mElements.push_back(std::move(text)); } -void TextFormatterNode::AppendElement(ArgumentType argument) { +void TextFormatterNode::AppendElement(ArgumentType argument) +{ int pinIdx = mInputs.size(); // Create pin mInputs.push_back(InputPin{}); @@ -150,7 +164,8 @@ void TextFormatterNode::AppendElement(ArgumentType argument) { }); } -void TextFormatterNode::RemoveElement(int idx) { +void TextFormatterNode::RemoveElement(int idx) +{ assert(idx >= 0 && idx < mElements.size()); PreRemoveElement(idx); @@ -160,7 +175,8 @@ void TextFormatterNode::RemoveElement(int idx) { mElements.erase(mElements.begin() + idx); } -void TextFormatterNode::Evaluate(WorkflowEvaluationContext& ctx) { +void TextFormatterNode::Evaluate(WorkflowEvaluationContext& ctx) +{ std::string result; result.reserve((size_t)(mMinOutputChars * 1.5f)); @@ -201,7 +217,8 @@ void TextFormatterNode::Evaluate(WorkflowEvaluationContext& ctx) { } } -void TextFormatterNode::PreRemoveElement(int idx) { +void TextFormatterNode::PreRemoveElement(int idx) +{ auto& elm = mElements[idx]; if (auto arg = std::get_if<Argument>(&elm)) { RemoveInputPin(arg->PinIdx); diff --git a/core/src/Model/Workflow/Nodes/TextNodes.hpp b/core/src/Model/Workflow/Nodes/TextNodes.hpp index 278db32..1beb145 100644 --- a/core/src/Model/Workflow/Nodes/TextNodes.hpp +++ b/core/src/Model/Workflow/Nodes/TextNodes.hpp @@ -7,9 +7,11 @@ #include <variant> #include <vector> -class TextFormatterNode : public WorkflowNode { +class TextFormatterNode : public WorkflowNode +{ public: - enum ArgumentType { + enum ArgumentType + { NumericArgument, TextArgument, DateTimeArgument, @@ -18,7 +20,8 @@ public: private: class Impl; - struct Argument { + struct Argument + { ArgumentType ArgumentType; int PinIdx; }; diff --git a/core/src/Model/Workflow/Nodes/UserInputNodes.cpp b/core/src/Model/Workflow/Nodes/UserInputNodes.cpp index 435cf6d..3a30631 100644 --- a/core/src/Model/Workflow/Nodes/UserInputNodes.cpp +++ b/core/src/Model/Workflow/Nodes/UserInputNodes.cpp @@ -3,24 +3,30 @@ #include "Model/Workflow/Evaluation.hpp" #include "Model/Workflow/Values/BasicValues.hpp" -bool FormInputNode::IsInstance(const WorkflowNode* node) { +bool FormInputNode::IsInstance(const WorkflowNode* node) +{ return node->GetKind() == KD_FormInput; } FormInputNode::FormInputNode() - : WorkflowNode(KD_FormInput) { + : WorkflowNode(KD_FormInput) +{ } -void FormInputNode::Evaluate(WorkflowEvaluationContext& ctx) { +void FormInputNode::Evaluate(WorkflowEvaluationContext& ctx) +{ } -bool DatabaseRowsInputNode::IsInstance(const WorkflowNode* node) { +bool DatabaseRowsInputNode::IsInstance(const WorkflowNode* node) +{ return node->GetKind() == KD_DatabaseRowsInput; } DatabaseRowsInputNode::DatabaseRowsInputNode() - : WorkflowNode(KD_DatabaseRowsInput) { + : WorkflowNode(KD_DatabaseRowsInput) +{ } -void DatabaseRowsInputNode::Evaluate(WorkflowEvaluationContext& ctx) { +void DatabaseRowsInputNode::Evaluate(WorkflowEvaluationContext& ctx) +{ } diff --git a/core/src/Model/Workflow/Nodes/UserInputNodes.hpp b/core/src/Model/Workflow/Nodes/UserInputNodes.hpp index fe66cb4..10ea95d 100644 --- a/core/src/Model/Workflow/Nodes/UserInputNodes.hpp +++ b/core/src/Model/Workflow/Nodes/UserInputNodes.hpp @@ -2,7 +2,8 @@ #include "Model/Workflow/Workflow.hpp" -class FormInputNode : public WorkflowNode { +class FormInputNode : public WorkflowNode +{ public: static bool IsInstance(const WorkflowNode* node); FormInputNode(); @@ -11,7 +12,8 @@ public: virtual void Evaluate(WorkflowEvaluationContext& ctx) override; }; -class DatabaseRowsInputNode : public WorkflowNode { +class DatabaseRowsInputNode : public WorkflowNode +{ public: static bool IsInstance(const WorkflowNode* node); DatabaseRowsInputNode(); diff --git a/core/src/Model/Workflow/Value.hpp b/core/src/Model/Workflow/Value.hpp index 2748e16..6cd42f3 100644 --- a/core/src/Model/Workflow/Value.hpp +++ b/core/src/Model/Workflow/Value.hpp @@ -3,9 +3,11 @@ #include <iosfwd> #include <memory> -class BaseValue { +class BaseValue +{ public: - enum Kind { + enum Kind + { KD_Numeric, KD_Text, KD_DateTime, diff --git a/core/src/Model/Workflow/Value_Main.cpp b/core/src/Model/Workflow/Value_Main.cpp index 2e64987..fdd2fd5 100644 --- a/core/src/Model/Workflow/Value_Main.cpp +++ b/core/src/Model/Workflow/Value_Main.cpp @@ -1,19 +1,24 @@ #include "Value.hpp" BaseValue::BaseValue(Kind kind) - : mKind{ kind } { + : mKind{ kind } +{ } -BaseValue::Kind BaseValue::GetKind() const { +BaseValue::Kind BaseValue::GetKind() const +{ return mKind; } -bool BaseValue::SupportsConstant() const { +bool BaseValue::SupportsConstant() const +{ return false; } -void BaseValue::ReadFrom(std::istream& stream) { +void BaseValue::ReadFrom(std::istream& stream) +{ } -void BaseValue::WriteTo(std::ostream& stream) { +void BaseValue::WriteTo(std::ostream& stream) +{ } diff --git a/core/src/Model/Workflow/Value_RTTI.cpp b/core/src/Model/Workflow/Value_RTTI.cpp index 2a1ac39..a660557 100644 --- a/core/src/Model/Workflow/Value_RTTI.cpp +++ b/core/src/Model/Workflow/Value_RTTI.cpp @@ -3,7 +3,8 @@ #include "Model/Workflow/Values/BasicValues.hpp" #include "Utils/Macros.hpp" -const char* BaseValue::FormatKind(Kind kind) { +const char* BaseValue::FormatKind(Kind kind) +{ switch (kind) { case KD_Numeric: return "Numeric"; case KD_Text: return "Text"; @@ -12,7 +13,8 @@ const char* BaseValue::FormatKind(Kind kind) { } } -std::unique_ptr<BaseValue> BaseValue::CreateByKind(BaseValue::Kind kind) { +std::unique_ptr<BaseValue> BaseValue::CreateByKind(BaseValue::Kind kind) +{ switch (kind) { case KD_Numeric: return std::make_unique<NumericValue>(); case KD_Text: return std::make_unique<TextValue>(); diff --git a/core/src/Model/Workflow/Values/BasicValues.cpp b/core/src/Model/Workflow/Values/BasicValues.cpp index 11d30b7..3f58de8 100644 --- a/core/src/Model/Workflow/Values/BasicValues.cpp +++ b/core/src/Model/Workflow/Values/BasicValues.cpp @@ -3,16 +3,19 @@ #include <charconv> #include <limits> -bool NumericValue::IsInstance(const BaseValue* value) { +bool NumericValue::IsInstance(const BaseValue* value) +{ return value->GetKind() == KD_Numeric; } NumericValue::NumericValue() - : BaseValue(BaseValue::KD_Numeric) { + : BaseValue(BaseValue::KD_Numeric) +{ } template <class T> -static std::string NumberToString(T value) { +static std::string NumberToString(T value) +{ constexpr auto kSize = std::numeric_limits<T>::max_digits10; char buf[kSize]; @@ -24,55 +27,68 @@ static std::string NumberToString(T value) { } } -std::string NumericValue::GetTruncatedString() const { +std::string NumericValue::GetTruncatedString() const +{ return ::NumberToString((int64_t)mValue); } -std::string NumericValue::GetRoundedString() const { +std::string NumericValue::GetRoundedString() const +{ return ::NumberToString((int64_t)std::round(mValue)); } -std::string NumericValue::GetString() const { +std::string NumericValue::GetString() const +{ return ::NumberToString(mValue); } -int64_t NumericValue::GetInt() const { +int64_t NumericValue::GetInt() const +{ return static_cast<int64_t>(mValue); } -double NumericValue::GetValue() const { +double NumericValue::GetValue() const +{ return mValue; } -void NumericValue::SetValue(double value) { +void NumericValue::SetValue(double value) +{ mValue = value; } -bool TextValue::IsInstance(const BaseValue* value) { +bool TextValue::IsInstance(const BaseValue* value) +{ return value->GetKind() == KD_Text; } TextValue::TextValue() - : BaseValue(BaseValue::KD_Text) { + : BaseValue(BaseValue::KD_Text) +{ } -const std::string& TextValue::GetValue() const { +const std::string& TextValue::GetValue() const +{ return mValue; } -void TextValue::SetValue(const std::string& value) { +void TextValue::SetValue(const std::string& value) +{ mValue = value; } -bool DateTimeValue::IsInstance(const BaseValue* value) { +bool DateTimeValue::IsInstance(const BaseValue* value) +{ return value->GetKind() == KD_DateTime; } DateTimeValue::DateTimeValue() - : BaseValue(BaseValue::KD_DateTime) { + : BaseValue(BaseValue::KD_DateTime) +{ } -std::string DateTimeValue::GetString() const { +std::string DateTimeValue::GetString() const +{ namespace chrono = std::chrono; auto t = chrono::system_clock::to_time_t(mValue); @@ -82,10 +98,12 @@ std::string DateTimeValue::GetString() const { return std::string(data); } -const std::chrono::time_point<std::chrono::system_clock>& DateTimeValue::GetValue() const { +const std::chrono::time_point<std::chrono::system_clock>& DateTimeValue::GetValue() const +{ return mValue; } -void DateTimeValue::SetValue(const std::chrono::time_point<std::chrono::system_clock>& value) { +void DateTimeValue::SetValue(const std::chrono::time_point<std::chrono::system_clock>& value) +{ mValue = value; } diff --git a/core/src/Model/Workflow/Values/BasicValues.hpp b/core/src/Model/Workflow/Values/BasicValues.hpp index e2e990d..795876e 100644 --- a/core/src/Model/Workflow/Values/BasicValues.hpp +++ b/core/src/Model/Workflow/Values/BasicValues.hpp @@ -6,7 +6,8 @@ #include <cstdint> #include <string> -class NumericValue : public BaseValue { +class NumericValue : public BaseValue +{ private: double mValue; @@ -23,7 +24,8 @@ public: void SetValue(double value); }; -class TextValue : public BaseValue { +class TextValue : public BaseValue +{ private: std::string mValue; @@ -35,7 +37,8 @@ public: void SetValue(const std::string& value); }; -class DateTimeValue : public BaseValue { +class DateTimeValue : public BaseValue +{ private: std::chrono::time_point<std::chrono::system_clock> mValue; diff --git a/core/src/Model/Workflow/Workflow.hpp b/core/src/Model/Workflow/Workflow.hpp index 139a96e..f26fff9 100644 --- a/core/src/Model/Workflow/Workflow.hpp +++ b/core/src/Model/Workflow/Workflow.hpp @@ -14,16 +14,19 @@ #include <variant> #include <vector> -class WorkflowConnection { +class WorkflowConnection +{ public: static constexpr auto kInvalidId = std::numeric_limits<size_t>::max(); - enum Direction { + enum Direction + { ManyToOne, OneToMany, }; - struct ConnectionPoint { + struct ConnectionPoint + { size_t Node; int Pin; @@ -48,17 +51,20 @@ public: void WriteTo(std::ostream& stream); }; -class WorkflowNode { +class WorkflowNode +{ public: static constexpr auto kInvalidId = std::numeric_limits<size_t>::max(); - enum Type { + enum Type + { InputType, TransformType, OutputType, }; - enum Kind { + enum Kind + { KD_NumericAddition, KD_NumericSubtraction, KD_NumericMultiplication, @@ -74,7 +80,8 @@ public: }; protected: - struct InputPin { + struct InputPin + { size_t Connection = WorkflowConnection::kInvalidId; BaseValue::Kind MatchingType = BaseValue::InvalidKind; bool ConnectionToConst = false; @@ -87,7 +94,8 @@ protected: WorkflowConnection::Direction GetSupportedDirection() const; }; - struct OutputPin { + struct OutputPin + { size_t Connection = WorkflowConnection::kInvalidId; BaseValue::Kind MatchingType = BaseValue::InvalidKind; bool AllowsMultipleConnections = false; @@ -165,7 +173,8 @@ protected: void OnDetach() {} }; -class Workflow { +class Workflow +{ private: friend class WorkflowEvaluationContext; @@ -208,12 +217,18 @@ public: /* Graph rebuild */ - struct GraphUpdate_Success {}; - struct GraphUpdate_NoWorkToDo {}; - struct GraphUpdate_UnsatisfiedDependencies { + struct GraphUpdate_Success + { + }; + struct GraphUpdate_NoWorkToDo + { + }; + struct GraphUpdate_UnsatisfiedDependencies + { std::vector<size_t> UnsatisfiedNodes; }; - struct GraphUpdate_UnreachableNodes { + struct GraphUpdate_UnreachableNodes + { std::vector<size_t> UnreachableNodes; }; @@ -228,7 +243,8 @@ public: /* Serialization */ - enum ReadResult { + enum ReadResult + { ReadSuccess, ReadInvalidVersion, }; diff --git a/core/src/Model/Workflow/Workflow_Main.cpp b/core/src/Model/Workflow/Workflow_Main.cpp index 84b4557..c3e3791 100644 --- a/core/src/Model/Workflow/Workflow_Main.cpp +++ b/core/src/Model/Workflow/Workflow_Main.cpp @@ -14,42 +14,49 @@ namespace ImNodes = ax::NodeEditor; WorkflowConnection::WorkflowConnection() : MultiConnections{} , SingleConnection{ WorkflowNode::kInvalidId, -1 } - , ConnectionDirection{ OneToMany } { + , ConnectionDirection{ OneToMany } +{ } -bool WorkflowConnection::IsValid() const { +bool WorkflowConnection::IsValid() const +{ return SingleConnection.Node != WorkflowNode::kInvalidId; } -std::span<WorkflowConnection::ConnectionPoint> WorkflowConnection::GetSourcePoints() { +std::span<WorkflowConnection::ConnectionPoint> WorkflowConnection::GetSourcePoints() +{ switch (ConnectionDirection) { case ManyToOne: return MultiConnections; case OneToMany: return { &SingleConnection, 1 }; } } -std::span<const WorkflowConnection::ConnectionPoint> WorkflowConnection::GetSourcePoints() const { +std::span<const WorkflowConnection::ConnectionPoint> WorkflowConnection::GetSourcePoints() const +{ switch (ConnectionDirection) { case ManyToOne: return MultiConnections; case OneToMany: return { &SingleConnection, 1 }; } } -std::span<WorkflowConnection::ConnectionPoint> WorkflowConnection::GetDestinationPoints() { +std::span<WorkflowConnection::ConnectionPoint> WorkflowConnection::GetDestinationPoints() +{ switch (ConnectionDirection) { case ManyToOne: return { &SingleConnection, 1 }; case OneToMany: return MultiConnections; } } -std::span<const WorkflowConnection::ConnectionPoint> WorkflowConnection::GetDestinationPoints() const { +std::span<const WorkflowConnection::ConnectionPoint> WorkflowConnection::GetDestinationPoints() const +{ switch (ConnectionDirection) { case ManyToOne: return { &SingleConnection, 1 }; case OneToMany: return MultiConnections; } } -static void DrawConnectionPoints(const std::vector<WorkflowConnection::ConnectionPoint>& points, const char* pinHint) { +static void DrawConnectionPoints(const std::vector<WorkflowConnection::ConnectionPoint>& points, const char* pinHint) +{ ImGui::Indent(32.0f); for (auto& pt : points) { ImGui::Text("{ Node = %llu, Pin (%s) = %d }", pt.Node, pinHint, pt.Pin); @@ -60,13 +67,15 @@ static void DrawConnectionPoints(const std::vector<WorkflowConnection::Connectio ImGui::Unindent(); } -static void DrawConnectionPoint(const WorkflowConnection::ConnectionPoint& point, const char* pinHint) { +static void DrawConnectionPoint(const WorkflowConnection::ConnectionPoint& point, const char* pinHint) +{ ImGui::Indent(32.0f); ImGui::Text("{ Node = %llu, Pin (%s) = %d }", point.Node, pinHint, point.Pin); ImGui::Unindent(); } -void WorkflowConnection::DrawDebugInfo() const { +void WorkflowConnection::DrawDebugInfo() const +{ ImGui::BeginTooltip(); switch (ConnectionDirection) { case ManyToOne: { @@ -88,14 +97,16 @@ void WorkflowConnection::DrawDebugInfo() const { ImGui::EndTooltip(); } -static WorkflowConnection::ConnectionPoint ReadConnectionPoint(std::istream& stream) { +static WorkflowConnection::ConnectionPoint ReadConnectionPoint(std::istream& stream) +{ WorkflowConnection::ConnectionPoint pt; stream >> pt.Node; stream >> pt.Pin; return pt; } -void WorkflowConnection::ReadFrom(std::istream& stream) { +void WorkflowConnection::ReadFrom(std::istream& stream) +{ int n; stream >> n; ConnectionDirection = (Direction)n; @@ -109,12 +120,14 @@ void WorkflowConnection::ReadFrom(std::istream& stream) { } } -static void WriteConnectionPoint(std::ostream& stream, const WorkflowConnection::ConnectionPoint& pt) { +static void WriteConnectionPoint(std::ostream& stream, const WorkflowConnection::ConnectionPoint& pt) +{ stream << pt.Node; stream << pt.Pin; } -void WorkflowConnection::WriteTo(std::ostream& stream) { +void WorkflowConnection::WriteTo(std::ostream& stream) +{ stream << (int)ConnectionDirection; ::WriteConnectionPoint(stream, SingleConnection); stream << (size_t)MultiConnections.size(); @@ -123,60 +136,74 @@ void WorkflowConnection::WriteTo(std::ostream& stream) { } } -bool WorkflowNode::InputPin::IsConstantConnection() const { +bool WorkflowNode::InputPin::IsConstantConnection() const +{ return ConnectionToConst && IsConnected(); } -bool WorkflowNode::InputPin::IsConnected() const { +bool WorkflowNode::InputPin::IsConnected() const +{ return Connection != WorkflowConnection::kInvalidId; } -BaseValue::Kind WorkflowNode::InputPin::GetMatchingType() const { +BaseValue::Kind WorkflowNode::InputPin::GetMatchingType() const +{ return MatchingType; } -WorkflowConnection::Direction WorkflowNode::InputPin::GetSupportedDirection() const { +WorkflowConnection::Direction WorkflowNode::InputPin::GetSupportedDirection() const +{ return AllowsMultipleConnections ? WorkflowConnection::ManyToOne : WorkflowConnection::OneToMany; } -bool WorkflowNode::OutputPin::IsConnected() const { +bool WorkflowNode::OutputPin::IsConnected() const +{ return Connection != WorkflowConnection::kInvalidId; } -BaseValue::Kind WorkflowNode::OutputPin::GetMatchingType() const { +BaseValue::Kind WorkflowNode::OutputPin::GetMatchingType() const +{ return MatchingType; } -WorkflowConnection::Direction WorkflowNode::OutputPin::GetSupportedDirection() const { +WorkflowConnection::Direction WorkflowNode::OutputPin::GetSupportedDirection() const +{ return AllowsMultipleConnections ? WorkflowConnection::OneToMany : WorkflowConnection::ManyToOne; } WorkflowNode::WorkflowNode(Kind kind) : mKind{ kind } - , mDepth{ -1 } { + , mDepth{ -1 } +{ } -Vec2i WorkflowNode::GetPosition() const { +Vec2i WorkflowNode::GetPosition() const +{ return mPosition; } -void WorkflowNode::SetPosition(const Vec2i& position) { +void WorkflowNode::SetPosition(const Vec2i& position) +{ mPosition = position; } -size_t WorkflowNode::GetId() const { +size_t WorkflowNode::GetId() const +{ return mId; } -WorkflowNode::Kind WorkflowNode::GetKind() const { +WorkflowNode::Kind WorkflowNode::GetKind() const +{ return mKind; } -int WorkflowNode::GetDepth() const { +int WorkflowNode::GetDepth() const +{ return mDepth; } -WorkflowNode::Type WorkflowNode::GetType() const { +WorkflowNode::Type WorkflowNode::GetType() const +{ if (IsInputNode()) { return InputType; } else if (IsOutputNode()) { @@ -186,39 +213,48 @@ WorkflowNode::Type WorkflowNode::GetType() const { } } -bool WorkflowNode::IsInputNode() const { +bool WorkflowNode::IsInputNode() const +{ return mInputs.size() == 0; } -bool WorkflowNode::IsOutputNode() const { +bool WorkflowNode::IsOutputNode() const +{ return mOutputs.size() == 0; } -void WorkflowNode::ConnectInput(int nodeId, WorkflowNode& output, int outputNodeId) { +void WorkflowNode::ConnectInput(int nodeId, WorkflowNode& output, int outputNodeId) +{ mWorkflow->Connect(*this, nodeId, output, outputNodeId); } -void WorkflowNode::DisconnectInput(int nodeId) { +void WorkflowNode::DisconnectInput(int nodeId) +{ mWorkflow->DisconnectByDestination(*this, nodeId); } -bool WorkflowNode::IsInputConnected(int nodeId) const { +bool WorkflowNode::IsInputConnected(int nodeId) const +{ return mInputs[nodeId].IsConnected(); } -void WorkflowNode::ConnectOutput(int nodeId, WorkflowNode& input, int inputNodeId) { +void WorkflowNode::ConnectOutput(int nodeId, WorkflowNode& input, int inputNodeId) +{ mWorkflow->Connect(input, inputNodeId, *this, nodeId); } -void WorkflowNode::DisconnectOutput(int nodeId) { +void WorkflowNode::DisconnectOutput(int nodeId) +{ mWorkflow->DisconnectBySource(*this, nodeId); } -bool WorkflowNode::IsOutputConnected(int nodeId) const { +bool WorkflowNode::IsOutputConnected(int nodeId) const +{ return mOutputs[nodeId].IsConnected(); } -void WorkflowNode::Draw() { +void WorkflowNode::Draw() +{ for (size_t i = 0; i < mInputs.size(); ++i) { auto& pin = mInputs[i]; ImNodes::BeginPin(i, ImNodes::PinKind::Input); @@ -233,7 +269,8 @@ void WorkflowNode::Draw() { } } -void WorkflowNode::DrawDebugInfo() const { +void WorkflowNode::DrawDebugInfo() const +{ ImGui::BeginTooltip(); ImGui::Text("Node kind: %s", FormatKind(mKind)); ImGui::Text("Node type: %s", FormatType(GetType())); @@ -243,17 +280,20 @@ void WorkflowNode::DrawDebugInfo() const { ImGui::EndTooltip(); } -void WorkflowNode::ReadFrom(std::istream& stream) { +void WorkflowNode::ReadFrom(std::istream& stream) +{ stream >> mId; stream >> mPosition.x >> mPosition.y; } -void WorkflowNode::WriteTo(std::ostream& stream) { +void WorkflowNode::WriteTo(std::ostream& stream) +{ stream << mId; stream << mPosition.x << mPosition.y; } -WorkflowNode::InputPin& WorkflowNode::InsertInputPin(int atIdx) { +WorkflowNode::InputPin& WorkflowNode::InsertInputPin(int atIdx) +{ assert(atIdx >= 0 && atIdx < mInputs.size()); mInputs.push_back(InputPin{}); @@ -264,7 +304,8 @@ WorkflowNode::InputPin& WorkflowNode::InsertInputPin(int atIdx) { return mInputs[atIdx]; } -void WorkflowNode::RemoveInputPin(int pin) { +void WorkflowNode::RemoveInputPin(int pin) +{ DisconnectInput(pin); for (int i = 0, end = (int)mInputs.size() - 1; i < end; ++i) { SwapInputPin(i, i + 1); @@ -272,7 +313,8 @@ void WorkflowNode::RemoveInputPin(int pin) { mInputs.resize(mInputs.size() - 1); } -void WorkflowNode::SwapInputPin(int a, int b) { +void WorkflowNode::SwapInputPin(int a, int b) +{ auto& pinA = mInputs[a]; auto& pinB = mInputs[b]; @@ -300,7 +342,8 @@ void WorkflowNode::SwapInputPin(int a, int b) { std::swap(pinA, pinB); } -WorkflowNode::OutputPin& WorkflowNode::InsertOutputPin(int atIdx) { +WorkflowNode::OutputPin& WorkflowNode::InsertOutputPin(int atIdx) +{ assert(atIdx >= 0 && atIdx < mOutputs.size()); mOutputs.push_back(OutputPin{}); @@ -311,7 +354,8 @@ WorkflowNode::OutputPin& WorkflowNode::InsertOutputPin(int atIdx) { return mOutputs[atIdx]; } -void WorkflowNode::RemoveOutputPin(int pin) { +void WorkflowNode::RemoveOutputPin(int pin) +{ DisconnectOutput(pin); for (int i = 0, end = (int)mOutputs.size() - 1; i < end; ++i) { SwapInputPin(i, i + 1); @@ -319,7 +363,8 @@ void WorkflowNode::RemoveOutputPin(int pin) { mOutputs.resize(mOutputs.size() - 1); } -void WorkflowNode::SwapOutputPin(int a, int b) { +void WorkflowNode::SwapOutputPin(int a, int b) +{ auto& pinA = mOutputs[a]; auto& pinB = mOutputs[b]; @@ -346,51 +391,63 @@ void WorkflowNode::SwapOutputPin(int a, int b) { std::swap(pinA, pinB); } -const std::vector<WorkflowConnection>& Workflow::GetConnections() const { +const std::vector<WorkflowConnection>& Workflow::GetConnections() const +{ return mConnections; } -std::vector<WorkflowConnection>& Workflow::GetConnections() { +std::vector<WorkflowConnection>& Workflow::GetConnections() +{ return mConnections; } -const std::vector<std::unique_ptr<WorkflowNode>>& Workflow::GetNodes() const { +const std::vector<std::unique_ptr<WorkflowNode>>& Workflow::GetNodes() const +{ return mNodes; } -std::vector<std::unique_ptr<WorkflowNode>>& Workflow::GetNodes() { +std::vector<std::unique_ptr<WorkflowNode>>& Workflow::GetNodes() +{ return mNodes; } -const std::vector<std::unique_ptr<BaseValue>>& Workflow::GetConstants() const { +const std::vector<std::unique_ptr<BaseValue>>& Workflow::GetConstants() const +{ return mConstants; } -std::vector<std::unique_ptr<BaseValue>>& Workflow::GetConstants() { +std::vector<std::unique_ptr<BaseValue>>& Workflow::GetConstants() +{ return mConstants; } -WorkflowConnection* Workflow::GetConnectionById(size_t id) { +WorkflowConnection* Workflow::GetConnectionById(size_t id) +{ return &mConnections[id]; } -WorkflowNode* Workflow::GetStepById(size_t id) { +WorkflowNode* Workflow::GetStepById(size_t id) +{ return mNodes[id].get(); } -BaseValue* Workflow::GetConstantById(size_t id) { +BaseValue* Workflow::GetConstantById(size_t id) +{ return mConstants[id].get(); } -const std::vector<std::vector<size_t>>& Workflow::GetDepthGroups() const { +const std::vector<std::vector<size_t>>& Workflow::GetDepthGroups() const +{ return mDepthGroups; } -bool Workflow::DoesDepthNeedsUpdate() const { +bool Workflow::DoesDepthNeedsUpdate() const +{ return mDepthsDirty; } -void Workflow::AddStep(std::unique_ptr<WorkflowNode> step) { +void Workflow::AddStep(std::unique_ptr<WorkflowNode> step) +{ auto [storage, id] = AllocWorkflowStep(); storage = std::move(step); storage->OnAttach(*this, id); @@ -398,7 +455,8 @@ void Workflow::AddStep(std::unique_ptr<WorkflowNode> step) { storage->mId = id; } -void Workflow::RemoveStep(size_t id) { +void Workflow::RemoveStep(size_t id) +{ auto& step = mNodes[id]; if (step == nullptr) return; @@ -407,7 +465,8 @@ void Workflow::RemoveStep(size_t id) { step->mId = WorkflowNode::kInvalidId; } -void Workflow::RemoveConnection(size_t id) { +void Workflow::RemoveConnection(size_t id) +{ auto& conn = mConnections[id]; if (!conn.IsValid()) return; @@ -426,7 +485,8 @@ void Workflow::RemoveConnection(size_t id) { mDepthsDirty = true; } -bool Workflow::Connect(WorkflowNode& sourceNode, int sourcePin, WorkflowNode& destinationNode, int destinationPin) { +bool Workflow::Connect(WorkflowNode& sourceNode, int sourcePin, WorkflowNode& destinationNode, int destinationPin) +{ auto& src = sourceNode.mOutputs[sourcePin]; auto& dst = destinationNode.mInputs[destinationPin]; @@ -496,7 +556,8 @@ bool Workflow::Connect(WorkflowNode& sourceNode, int sourcePin, WorkflowNode& de // TODO cleanup these two implementation -bool Workflow::DisconnectBySource(WorkflowNode& sourceNode, int sourcePin) { +bool Workflow::DisconnectBySource(WorkflowNode& sourceNode, int sourcePin) +{ auto& sp = sourceNode.mOutputs[sourcePin]; if (!sp.IsConnected()) return false; @@ -530,7 +591,8 @@ bool Workflow::DisconnectBySource(WorkflowNode& sourceNode, int sourcePin) { return true; } -bool Workflow::DisconnectByDestination(WorkflowNode& destinationNode, int destinationPin) { +bool Workflow::DisconnectByDestination(WorkflowNode& destinationNode, int destinationPin) +{ auto& dp = destinationNode.mInputs[destinationPin]; if (!dp.IsConnected()) return false; if (dp.IsConstantConnection()) { @@ -569,7 +631,8 @@ bool Workflow::DisconnectByDestination(WorkflowNode& destinationNode, int destin return true; } -Workflow::GraphUpdateResult Workflow::UpdateGraph(bool getInfo) { +Workflow::GraphUpdateResult Workflow::UpdateGraph(bool getInfo) +{ if (!mDepthsDirty) { return GraphUpdate_NoWorkToDo{}; } @@ -578,7 +641,8 @@ Workflow::GraphUpdateResult Workflow::UpdateGraph(bool getInfo) { // - Dependency = nodes its input pins are connected to // - Dependents = nodes its output pins are connected to - struct WorkingNode { + struct WorkingNode + { // The max depth out of all dependency nodes, maintained during the traversal and committed as the actual depth // when all dependencies of this node has been resolved. Add 1 to get the depth that will be assigned to the node. int MaximumDepth = 0; @@ -688,7 +752,8 @@ Workflow::GraphUpdateResult Workflow::UpdateGraph(bool getInfo) { return GraphUpdate_Success{}; } -Workflow::ReadResult Workflow::ReadFrom(std::istream& stream) { +Workflow::ReadResult Workflow::ReadFrom(std::istream& stream) +{ auto DeserializeV0 = [&]() { size_t connectionsStorage, nodesStorage, constantsStorage; stream >> connectionsStorage >> nodesStorage >> constantsStorage; @@ -738,7 +803,8 @@ Workflow::ReadResult Workflow::ReadFrom(std::istream& stream) { return ReadSuccess; } -void Workflow::WriteTo(std::ostream& stream) { +void Workflow::WriteTo(std::ostream& stream) +{ // Version stream << (uint64_t)0; @@ -774,7 +840,8 @@ void Workflow::WriteTo(std::ostream& stream) { } } -std::pair<WorkflowConnection&, size_t> Workflow::AllocWorkflowConnection() { +std::pair<WorkflowConnection&, size_t> Workflow::AllocWorkflowConnection() +{ for (size_t idx = 0; idx < mConnections.size(); ++idx) { auto& elm = mConnections[idx]; if (!elm.IsValid()) { @@ -786,7 +853,8 @@ std::pair<WorkflowConnection&, size_t> Workflow::AllocWorkflowConnection() { return { mConnections.emplace_back(WorkflowConnection{}), id }; } -std::pair<std::unique_ptr<WorkflowNode>&, size_t> Workflow::AllocWorkflowStep() { +std::pair<std::unique_ptr<WorkflowNode>&, size_t> Workflow::AllocWorkflowStep() +{ for (size_t idx = 0; idx < mNodes.size(); ++idx) { auto& elm = mNodes[idx]; if (elm == nullptr) { diff --git a/core/src/Model/Workflow/Workflow_RTTI.cpp b/core/src/Model/Workflow/Workflow_RTTI.cpp index e3fafdb..0f8fd2e 100644 --- a/core/src/Model/Workflow/Workflow_RTTI.cpp +++ b/core/src/Model/Workflow/Workflow_RTTI.cpp @@ -8,7 +8,8 @@ #include <memory> -const char* WorkflowNode::FormatKind(Kind kind) { +const char* WorkflowNode::FormatKind(Kind kind) +{ switch (kind) { case KD_NumericAddition: return "NumericOperation (addition)"; case KD_NumericSubtraction: return "NumericOperation (subtraction)"; @@ -24,7 +25,8 @@ const char* WorkflowNode::FormatKind(Kind kind) { } } -const char* WorkflowNode::FormatType(Type type) { +const char* WorkflowNode::FormatType(Type type) +{ switch (type) { case InputType: return "input"; case TransformType: return "transform"; @@ -32,7 +34,8 @@ const char* WorkflowNode::FormatType(Type type) { } } -std::unique_ptr<WorkflowNode> WorkflowNode::CreateByKind(WorkflowNode::Kind kind) { +std::unique_ptr<WorkflowNode> WorkflowNode::CreateByKind(WorkflowNode::Kind kind) +{ switch (kind) { case KD_NumericAddition: return std::make_unique<NumericOperationNode>(NumericOperationNode::Addition); case KD_NumericSubtraction: return std::make_unique<NumericOperationNode>(NumericOperationNode::Subtraction); diff --git a/core/src/UI/Localization.hpp b/core/src/UI/Localization.hpp index 777c161..043170a 100644 --- a/core/src/UI/Localization.hpp +++ b/core/src/UI/Localization.hpp @@ -7,7 +7,8 @@ using namespace std::literals::string_view_literals; -class LocaleStrings { +class LocaleStrings +{ public: static std::unique_ptr<LocaleStrings> Instance; diff --git a/core/src/UI/States.cpp b/core/src/UI/States.cpp index 546e1ab..b7b4c9f 100644 --- a/core/src/UI/States.cpp +++ b/core/src/UI/States.cpp @@ -8,22 +8,26 @@ static std::unique_ptr<UIState> uiStateInstance; -void UIState::Init() { +void UIState::Init() +{ uiStateInstance = std::make_unique<UIState>(); } -void UIState::Shutdown() { +void UIState::Shutdown() +{ if (uiStateInstance) { uiStateInstance->CloseCurrentProject(); uiStateInstance = nullptr; } } -UIState& UIState::GetInstance() { +UIState& UIState::GetInstance() +{ return *uiStateInstance; } -void UIState::SetCurrentProject(std::unique_ptr<Project> project) { +void UIState::SetCurrentProject(std::unique_ptr<Project> project) +{ CloseCurrentProject(); if (project) { GlobalStates::GetInstance().MoveProjectToTop(*project); @@ -31,7 +35,8 @@ void UIState::SetCurrentProject(std::unique_ptr<Project> project) { CurrentProject = std::move(project); } -void UIState::CloseCurrentProject() { +void UIState::CloseCurrentProject() +{ if (CurrentProject) { CurrentProject->WriteToDisk(); CurrentProject = nullptr; diff --git a/core/src/UI/States.hpp b/core/src/UI/States.hpp index 4cc3b0f..d314494 100644 --- a/core/src/UI/States.hpp +++ b/core/src/UI/States.hpp @@ -2,12 +2,13 @@ #include "cplt_fwd.hpp" -#include <memory> #include <imgui.h> +#include <memory> /// Minimal state shared by all UI components, such as database, items, export, etc. /// Note that global components (settings) is not supposed to access these. -class UIState { +class UIState +{ public: static void Init(); static void Shutdown(); diff --git a/core/src/UI/UI_DatabaseView.cpp b/core/src/UI/UI_DatabaseView.cpp index 96009fb..bc458da 100644 --- a/core/src/UI/UI_DatabaseView.cpp +++ b/core/src/UI/UI_DatabaseView.cpp @@ -10,7 +10,9 @@ #include <IconsFontAwesome.h> #include <SQLiteCpp/Statement.h> #include <imgui.h> +#include <tsl/robin_map.h> #include <cstdint> +#include <iostream> #include <memory> #include <vector> @@ -19,27 +21,36 @@ namespace { // TODO move to Settings constexpr int kMaxEntriesPerPage = 20; -class SaleEntry { -public: - std::string Customer; - std::string Deadline; - std::string DeliveryTime; +enum class DeliveryDirection +{ + FactoryToWarehouse, + WarehouseToCustomer, }; -class PurchaseEntry { -public: - std::string Factory; - std::string OrderTime; - std::string DeliveryTime; +struct DeliveryEntry +{ + std::string ShipmentTime; + std::string ArriveTime; + DeliveryDirection Direction; + + const char* StringifyDirection() const + { + switch (Direction) { + case DeliveryDirection::FactoryToWarehouse: return "Factory to warehouse"; + case DeliveryDirection::WarehouseToCustomer: return "Warehouse to customer"; + } + } }; -class GenericTableView { +class GenericTableView +{ protected: // Translation entries for implementer to fill out const char* mEditDialogTitle; SQLite::Statement* mGetRowCountStatement; SQLite::Statement* mGetRowsStatement; + SQLite::Statement* mFilterRowsStatement; Project* mProject; @@ -69,28 +80,33 @@ protected: int mSelectedEntryRowId; public: - static int CalcPageForRowId(int64_t rowId) { + static int CalcPageForRowId(int64_t rowId) + { return rowId / kMaxEntriesPerPage; } /// Calculate range [begin, end) of index for the list of entries that are currently visible that the path-th page would show. /// i.e. when there is a filter, look into \c mActiveEntryIndices; when there is no filter, use directly. - static std::pair<int64_t, int64_t> CalcRangeForPage(int page) { + static std::pair<int64_t, int64_t> CalcRangeForPage(int page) + { int begin = page * kMaxEntriesPerPage; return { begin, begin + kMaxEntriesPerPage }; } - Project* GetProject() const { + Project* GetProject() const + { return mProject; } - virtual void OnProjectChanged(Project* newProject) { + virtual void OnProjectChanged(Project* newProject) + { mProject = newProject; if (mGetRowCountStatement->executeStep()) { mRowCount = mGetRowCountStatement->getColumn(0).getInt(); } else { - // TODO report error + std::cerr << "Failed to fetch row count from SQLite.\n"; + mRowCount = 0; } mFirstCachedRowId = 0; @@ -105,13 +121,16 @@ public: mSelectedEntryRowId = -1; } - TableRowsFilter* GetFilter() const { + TableRowsFilter* GetFilter() const + { return mActiveFilter.get(); } - virtual void OnFilterChanged() { - auto& stmt = mProject->GetTransactionsModel().GetSales().FilterRowsStatement; - DEFER { + virtual void OnFilterChanged() + { + auto& stmt = *mFilterRowsStatement; + DEFER + { stmt.reset(); }; @@ -128,12 +147,14 @@ public: mSelectedEntryRowId = -1; } - void OnFilterChanged(std::unique_ptr<TableRowsFilter> filter) { + void OnFilterChanged(std::unique_ptr<TableRowsFilter> filter) + { mActiveFilter = std::move(filter); OnFilterChanged(); } - void Draw() { + void Draw() + { bool dummy = true; auto ls = LocaleStrings::Instance.get(); @@ -161,8 +182,24 @@ public: ImGui::EndPopup(); } - if (ImGui::BeginTable("", GetTableColumnCount())) { + ImGui::SameLine(); + if (ImGui::Button(ls->Add.Get())) { + // TODO + } + + if (mSelectedEntryRowId == -1) { + DrawMainTable(); + } else { + // TODO better layout + DrawMainTable(); + ImGui::SameLine(); + DrawDeliveriesTable(); + } + } + void DrawMainTable() + { + if (ImGui::BeginTable("DataTable", GetTableColumnCount(), ImGuiTableFlags_ScrollX)) { SetupTableColumns(); ImGui::TableHeadersRow(); @@ -184,34 +221,94 @@ public: } } - void SetPage(int page) { + void DrawDeliveriesTable() + { + if (ImGui::BeginTable("DeliveriesTable", 2)) { + + ImGui::TableSetupColumn("Shipment time"); + ImGui::TableSetupColumn("Arrival time"); + ImGui::TableHeadersRow(); + + auto& deliveries = GetEntryAssociatedDeliveries(mSelectedEntryRowId); + for (auto& delivery : deliveries) { + ImGui::TableNextRow(); + + ImGui::TableNextColumn(); + ImGui::TextUnformatted(delivery.ShipmentTime.c_str()); + + ImGui::TableNextColumn(); + ImGui::TextUnformatted(delivery.ArriveTime.c_str()); + } + + ImGui::EndTable(); + } + } + + void SetPage(int page) + { mCurrentPage = page; EnsureCacheCoversPage(page); } - int RowIdToIndex(int64_t rowId) const { + int RowIdToIndex(int64_t rowId) const + { return rowId - mFirstCachedRowId; } - int64_t IndexToRowId(int index) const { + int64_t IndexToRowId(int index) const + { return index + mFirstCachedRowId; } + std::vector<DeliveryEntry> LoadDeliveriesEntries(int64_t orderRowId, DeliveryDirection type) + { + bool outgoingFlag; + switch (type) { + case DeliveryDirection::FactoryToWarehouse: outgoingFlag = false; break; + case DeliveryDirection::WarehouseToCustomer: outgoingFlag = true; break; + } + + auto& stmt = mProject->GetTransactionsModel().GetDeliveries().FilterByTypeAndId; + DEFER + { + stmt.reset(); + }; + + stmt.bind(1, orderRowId); + stmt.bind(2, static_cast<int>(type)); + + std::vector<DeliveryEntry> entries; + int sendTimeCol = stmt.getColumnIndex("ShipmentTime"); + int arrivalTimeCol = stmt.getColumnIndex("ArrivalTime"); + while (stmt.executeStep()) { + entries.push_back(DeliveryEntry{ + .ShipmentTime = StringifyTimeStamp(stmt.getColumn(arrivalTimeCol).getInt64()), + .ArriveTime = StringifyTimeStamp(stmt.getColumn(sendTimeCol).getInt64()), + .Direction = type, + }); + } + + return entries; + } + protected: virtual int GetTableColumnCount() const = 0; virtual void SetupTableColumns() = 0; + virtual const std::vector<DeliveryEntry>& GetEntryAssociatedDeliveries(int rowId) = 0; virtual void DisplayEntry(int rowId) = 0; virtual void EditEntry(int rowId) = 0; virtual void ClearEntries() = 0; - void EnsureCacheCoversPage(int page) { + void EnsureCacheCoversPage(int page) + { auto [begin, end] = CalcRangeForPage(page); EnsureCacheCovers(begin, end - 1); } - void EnsureCacheCovers(int64_t firstRow, int64_t lastRow) { + void EnsureCacheCovers(int64_t firstRow, int64_t lastRow) + { if (firstRow > lastRow) { std::swap(firstRow, lastRow); } @@ -239,7 +336,21 @@ protected: virtual void EnsureCacheCoversImpl(int newFirst, int newLast) = 0; template <class TEntry, class TCollector> - std::vector<TEntry> LoadRange(int64_t begin, int64_t end, TCollector&& collector) { + void LoadExtraEntries(std::vector<TEntry>& entries, int newFirst, int newLast, TCollector&& collector) + { + auto front = LoadRange<TEntry>(newFirst, mFirstCachedRowId, collector); + auto back = LoadRange<TEntry>(mLastCachedRowId + 1, newLast + 1, collector); + + mFirstCachedRowId -= front.size(); + mLastCachedRowId += back.size(); + + entries.insert(entries.begin(), std::make_move_iterator(front.begin()), std::make_move_iterator(front.end())); + entries.insert(entries.end(), std::make_move_iterator(back.begin()), std::make_move_iterator(back.end())); + } + + template <class TEntry, class TCollector> + std::vector<TEntry> LoadRange(int64_t begin, int64_t end, TCollector&& collector) + { std::vector<TEntry> result; size_t size = end - begin; @@ -249,10 +360,10 @@ protected: result.reserve(size); - DEFER { + DEFER + { mGetRowsStatement->reset(); }; - mGetRowsStatement->bind(1, begin); mGetRowsStatement->bind(2, end); @@ -260,46 +371,75 @@ protected: return result; } - void UpdateLastPage() { +private: + void UpdateLastPage() + { mLastPage = mActiveEntries.empty() ? CalcPageForRowId(mRowCount) : CalcPageForRowId(mActiveEntries.back()); } }; -class SalesTableView : public GenericTableView { +class SaleEntry +{ +public: + std::vector<DeliveryEntry> AssociatedDeliveries; + std::string Customer; + std::string Deadline; + std::string DeliveryTime; + bool DeliveriesCached = false; +}; + +class SalesTableView : public GenericTableView +{ private: /// A cached, contiguous (row id of each entry is monotonically increasing, but not necessarily starts at 0) list ready-to-be-presented entries. May be incomplete. std::vector<SaleEntry> mEntries; public: - SalesTableView() { + SalesTableView() + { auto ls = LocaleStrings::Instance.get(); mEditDialogTitle = ls->EditSaleEntryDialogTitle.Get(); } - virtual void OnProjectChanged(Project* newProject) override { + virtual void OnProjectChanged(Project* newProject) override + { auto& sales = newProject->GetTransactionsModel().GetSales(); - mGetRowCountStatement = &sales.GetRowCountStatement; - mGetRowsStatement = &sales.GetRowsStatement; + mGetRowCountStatement = &sales.GetRowCount; + mGetRowsStatement = &sales.GetRows; + // mFilterRowsStatement = &sales.FilterRows; GenericTableView::OnProjectChanged(newProject); } protected: - virtual int GetTableColumnCount() const override { + virtual int GetTableColumnCount() const override + { return 3; } - virtual void SetupTableColumns() override { + virtual void SetupTableColumns() override + { auto ls = LocaleStrings::Instance.get(); ImGui::TableSetupColumn(ls->DatabaseCustomerColumn.Get()); ImGui::TableSetupColumn(ls->DatabaseDeadlineColumn.Get()); ImGui::TableSetupColumn(ls->DatabaseDeliveryTimeColumn.Get()); } - virtual void DisplayEntry(int rowId) override { - auto& entry = GetEntry(rowId); + virtual const std::vector<DeliveryEntry>& GetEntryAssociatedDeliveries(int rowId) override + { + auto& entry = mEntries[RowIdToIndex(rowId)]; + if (!entry.DeliveriesCached) { + entry.AssociatedDeliveries = LoadDeliveriesEntries(rowId, DeliveryDirection::FactoryToWarehouse); + entry.DeliveriesCached = true; + } + return entry.AssociatedDeliveries; + } + + virtual void DisplayEntry(int rowId) override + { + auto& entry = mEntries[RowIdToIndex(rowId)]; auto ls = LocaleStrings::Instance.get(); ImGui::PushID(rowId); @@ -323,15 +463,18 @@ protected: ImGui::PopID(); } - virtual void EditEntry(int rowId) override { - // TODO + virtual void EditEntry(int rowId) override + { + // `TODO` } - virtual void ClearEntries() override { + virtual void ClearEntries() override + { mEntries.clear(); } - virtual void EnsureCacheCoversImpl(int newFirst, int newLast) override { + virtual void EnsureCacheCoversImpl(int newFirst, int newLast) override + { auto CollectRows = [&](std::vector<SaleEntry>& result) { auto& stmt = *mGetRowsStatement; int customerCol = stmt.getColumnIndex("Customer"); @@ -350,53 +493,69 @@ protected: } }; - auto front = LoadRange<SaleEntry>(newFirst, mFirstCachedRowId, CollectRows); - auto back = LoadRange<SaleEntry>(mLastCachedRowId + 1, newLast + 1, CollectRows); - - mFirstCachedRowId -= front.size(); - mLastCachedRowId += back.size(); - - mEntries.insert(mEntries.begin(), std::make_move_iterator(front.begin()), std::make_move_iterator(front.end())); - mEntries.insert(mEntries.end(), std::make_move_iterator(back.begin()), std::make_move_iterator(back.end())); + LoadExtraEntries<SaleEntry>(mEntries, newFirst, newLast, CollectRows); } +}; - SaleEntry& GetEntry(int rowId) { - return mEntries[RowIdToIndex(rowId)]; - } +class PurchaseEntry +{ +public: + std::vector<DeliveryEntry> AssociatedDeliveries; + std::string Factory; + std::string OrderTime; + std::string DeliveryTime; + bool DeliveriesCached; }; -class PurchasesTableView : public GenericTableView { +class PurchasesTableView : public GenericTableView +{ private: std::vector<PurchaseEntry> mEntries; public: - PurchasesTableView() { + PurchasesTableView() + { auto ls = LocaleStrings::Instance.get(); mEditDialogTitle = ls->EditPurchaseEntryDialogTitle.Get(); } - virtual void OnProjectChanged(Project* newProject) override { + virtual void OnProjectChanged(Project* newProject) override + { auto& purchases = newProject->GetTransactionsModel().GetPurchases(); - mGetRowCountStatement = &purchases.GetRowCountStatement; - mGetRowsStatement = &purchases.GetRowsStatement; + mGetRowCountStatement = &purchases.GetRowCount; + mGetRowsStatement = &purchases.GetRows; + // mFilterRowsStatement = &purchases.FilterRowsStatement; GenericTableView::OnProjectChanged(newProject); } protected: - virtual int GetTableColumnCount() const override { + virtual int GetTableColumnCount() const override + { return 3; } - virtual void SetupTableColumns() override { + virtual void SetupTableColumns() override + { auto ls = LocaleStrings::Instance.get(); ImGui::TableSetupColumn(ls->DatabaseFactoryColumn.Get()); ImGui::TableSetupColumn(ls->DatabaseOrderTimeColumn.Get()); ImGui::TableSetupColumn(ls->DatabaseDeliveryTimeColumn.Get()); } - virtual void DisplayEntry(int rowId) override { - auto& entry = GetEntry(rowId); + virtual const std::vector<DeliveryEntry>& GetEntryAssociatedDeliveries(int rowId) override + { + auto& entry = mEntries[RowIdToIndex(rowId)]; + if (!entry.DeliveriesCached) { + entry.AssociatedDeliveries = LoadDeliveriesEntries(rowId, DeliveryDirection::FactoryToWarehouse); + entry.DeliveriesCached = true; + } + return entry.AssociatedDeliveries; + } + + virtual void DisplayEntry(int rowId) override + { + auto& entry = mEntries[RowIdToIndex(rowId)]; auto ls = LocaleStrings::Instance.get(); ImGui::PushID(rowId); @@ -424,15 +583,18 @@ protected: ImGui::PopID(); } - virtual void EditEntry(int rowId) override { + virtual void EditEntry(int rowId) override + { // TODO } - virtual void ClearEntries() override { + virtual void ClearEntries() override + { mEntries.clear(); } - virtual void EnsureCacheCoversImpl(int newFirst, int newLast) override { + virtual void EnsureCacheCoversImpl(int newFirst, int newLast) override + { auto CollectRows = [&](std::vector<PurchaseEntry>& result) { auto& stmt = *mGetRowsStatement; int factoryCol = stmt.getColumnIndex("Factory"); @@ -451,23 +613,13 @@ protected: } }; - auto front = LoadRange<PurchaseEntry>(newFirst, mFirstCachedRowId, CollectRows); - auto back = LoadRange<PurchaseEntry>(mLastCachedRowId + 1, newLast + 1, CollectRows); - - mFirstCachedRowId -= front.size(); - mLastCachedRowId += back.size(); - - mEntries.insert(mEntries.begin(), std::make_move_iterator(front.begin()), std::make_move_iterator(front.end())); - mEntries.insert(mEntries.end(), std::make_move_iterator(back.begin()), std::make_move_iterator(back.end())); - } - - PurchaseEntry& GetEntry(int rowId) { - return mEntries[RowIdToIndex(rowId)]; + LoadExtraEntries<PurchaseEntry>(mEntries, newFirst, newLast, CollectRows); } }; } // namespace -void UI::DatabaseViewTab() { +void UI::DatabaseViewTab() +{ auto ls = LocaleStrings::Instance.get(); auto& uis = UIState::GetInstance(); diff --git a/core/src/UI/UI_Items.cpp b/core/src/UI/UI_Items.cpp index 624f942..8633c1f 100644 --- a/core/src/UI/UI_Items.cpp +++ b/core/src/UI/UI_Items.cpp @@ -10,7 +10,8 @@ namespace { -enum class ActionResult { +enum class ActionResult +{ Confirmed, Canceled, Pending, @@ -19,9 +20,16 @@ enum class ActionResult { /// \param list Item list that the item is in. /// \param item A non-null pointer to the currently being edited item. It should not change until this function returns a non-\c ActionResult::Pending value. template <class T> -ActionResult ItemEditor(ItemList<T>& list, T* item) { - constexpr bool kHasDescription = requires(T t) { t.GetDescription(); }; - constexpr bool kHasEmail = requires(T t) { t.GetEmail(); }; +ActionResult ItemEditor(ItemList<T>& list, T* item) +{ + constexpr bool kHasDescription = requires(T t) + { + t.GetDescription(); + }; + constexpr bool kHasEmail = requires(T t) + { + t.GetEmail(); + }; auto ls = LocaleStrings::Instance.get(); auto& uis = UIState::GetInstance(); @@ -88,11 +96,24 @@ ActionResult ItemEditor(ItemList<T>& list, T* item) { } template <class T> -void ItemListEntries(ItemList<T>& list, int& selectedIdx) { - constexpr bool kHasDescription = requires(T t) { t.GetDescription(); }; - constexpr bool kHasEmail = requires(T t) { t.GetEmail(); }; - constexpr bool kHasStock = requires(T t) { t.GetPrice(); }; - constexpr bool kHasPrice = requires(T t) { t.GetPrice(); }; +void ItemListEntries(ItemList<T>& list, int& selectedIdx) +{ + constexpr bool kHasDescription = requires(T t) + { + t.GetDescription(); + }; + constexpr bool kHasEmail = requires(T t) + { + t.GetEmail(); + }; + constexpr bool kHasStock = requires(T t) + { + t.GetPrice(); + }; + constexpr bool kHasPrice = requires(T t) + { + t.GetPrice(); + }; constexpr int kColumns = 1 /* Name column */ + kHasDescription + kHasEmail + kHasStock + kHasPrice; auto ls = LocaleStrings::Instance.get(); @@ -148,7 +169,8 @@ void ItemListEntries(ItemList<T>& list, int& selectedIdx) { } template <class T> -void ItemListEditor(ItemList<T>& list) { +void ItemListEditor(ItemList<T>& list) +{ auto ls = LocaleStrings::Instance.get(); bool opened = true; @@ -216,7 +238,8 @@ void ItemListEditor(ItemList<T>& list) { } } // namespace -void UI::ItemsTab() { +void UI::ItemsTab() +{ auto ls = LocaleStrings::Instance.get(); auto& uis = UIState::GetInstance(); diff --git a/core/src/UI/UI_MainWindow.cpp b/core/src/UI/UI_MainWindow.cpp index 4f09281..62a195e 100644 --- a/core/src/UI/UI_MainWindow.cpp +++ b/core/src/UI/UI_MainWindow.cpp @@ -15,7 +15,8 @@ namespace fs = std::filesystem; namespace { -void ProjectTab_Normal() { +void ProjectTab_Normal() +{ auto ls = LocaleStrings::Instance.get(); auto& gs = GlobalStates::GetInstance(); auto& uis = UIState::GetInstance(); @@ -33,7 +34,8 @@ void ProjectTab_Normal() { ImGui::Text("%s%s", ls->ActiveProjectPath.Get(), uis.CurrentProject->GetPathString().c_str()); } -void ProjectTab_NoProject() { +void ProjectTab_NoProject() +{ auto ls = LocaleStrings::Instance.get(); auto& gs = GlobalStates::GetInstance(); auto& uis = UIState::GetInstance(); @@ -186,7 +188,8 @@ void ProjectTab_NoProject() { } } // namespace -void UI::MainWindow() { +void UI::MainWindow() +{ auto ls = LocaleStrings::Instance.get(); auto& uis = UIState::GetInstance(); diff --git a/core/src/UI/UI_Settings.cpp b/core/src/UI/UI_Settings.cpp index 3dbb0d2..da935c6 100644 --- a/core/src/UI/UI_Settings.cpp +++ b/core/src/UI/UI_Settings.cpp @@ -4,6 +4,7 @@ #include <imgui.h> -void UI::SettingsTab() { +void UI::SettingsTab() +{ // TODO } diff --git a/core/src/UI/UI_Utils.cpp b/core/src/UI/UI_Utils.cpp index 06fd55e..15f88cf 100644 --- a/core/src/UI/UI_Utils.cpp +++ b/core/src/UI/UI_Utils.cpp @@ -4,31 +4,37 @@ #include <imgui.h> #include <imgui_internal.h> -void ImGui::SetNextWindowSizeRelScreen(float xPercent, float yPercent, ImGuiCond cond) { +void ImGui::SetNextWindowSizeRelScreen(float xPercent, float yPercent, ImGuiCond cond) +{ auto vs = ImGui::GetMainViewport()->Size; ImGui::SetNextWindowSize({ vs.x * xPercent, vs.y * yPercent }, cond); } -void ImGui::SetNextWindowCentered(ImGuiCond cond) { +void ImGui::SetNextWindowCentered(ImGuiCond cond) +{ auto vs = ImGui::GetMainViewport()->Size; ImGui::SetNextWindowPos({ vs.x / 2, vs.y / 2 }, cond, { 0.5f, 0.5f }); } -void ImGui::PushDisabled() { +void ImGui::PushDisabled() +{ ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.5f * ImGui::GetStyle().Alpha); } -void ImGui::PopDisabled() { +void ImGui::PopDisabled() +{ ImGui::PopItemFlag(); ImGui::PopStyleVar(); } -bool ImGui::Button(const char* label, bool disabled) { +bool ImGui::Button(const char* label, bool disabled) +{ return Button(label, ImVec2{}, disabled); } -bool ImGui::Button(const char* label, const ImVec2& sizeArg, bool disabled) { +bool ImGui::Button(const char* label, const ImVec2& sizeArg, bool disabled) +{ if (disabled) PushDisabled(); bool res = ImGui::Button(label, sizeArg); if (disabled) PopDisabled(); @@ -36,13 +42,15 @@ bool ImGui::Button(const char* label, const ImVec2& sizeArg, bool disabled) { return res; } -void ImGui::ErrorIcon() { +void ImGui::ErrorIcon() +{ ImGui::PushStyleColor(ImGuiCol_Text, ImVec4{ 237 / 255.0f, 67 / 255.0f, 55 / 255.0f, 1.0f }); // #ED4337 ImGui::Text(ICON_FA_EXCLAMATION_CIRCLE); ImGui::PopStyleColor(); } -void ImGui::ErrorMessage(const char* fmt, ...) { +void ImGui::ErrorMessage(const char* fmt, ...) +{ ErrorIcon(); SameLine(); @@ -52,13 +60,15 @@ void ImGui::ErrorMessage(const char* fmt, ...) { va_end(args); } -void ImGui::WarningIcon() { +void ImGui::WarningIcon() +{ ImGui::PushStyleColor(ImGuiCol_Text, ImVec4{ 255 / 255.0f, 184 / 255.0f, 24 / 255.0f, 1.0f }); // #FFB818 ImGui::Text(ICON_FA_EXCLAMATION_TRIANGLE); ImGui::PopStyleColor(); } -void ImGui::WarningMessage(const char* fmt, ...) { +void ImGui::WarningMessage(const char* fmt, ...) +{ WarningIcon(); SameLine(); diff --git a/core/src/UI/UI_Workflows.cpp b/core/src/UI/UI_Workflows.cpp index fe504e2..108410c 100644 --- a/core/src/UI/UI_Workflows.cpp +++ b/core/src/UI/UI_Workflows.cpp @@ -17,11 +17,13 @@ namespace ImNodes = ax::NodeEditor; namespace { -class WorkflowCreationMenu { +class WorkflowCreationMenu +{ private: using WorkflowNodeConstructor = std::unique_ptr<WorkflowNode> (*)(); - enum Category { + enum Category + { NumericCategory, TextCategory, DocumentsCategory, @@ -30,7 +32,8 @@ private: OutputCategory, }; - struct Candidate { + struct Candidate + { WorkflowNodeConstructor Constructor; std::string Name; Category Category; @@ -39,7 +42,10 @@ private: std::vector<Candidate> mCandidates; #define SUB_RANGE_ACCESS(Type, AccessorName, storage, begin, nextBegin) \ - std::span<Type> AccessorName() { return { &storage[begin], (size_t)(nextBegin - begin) }; } + std::span<Type> AccessorName() \ + { \ + return { &storage[begin], (size_t)(nextBegin - begin) }; \ + } int mTextOffset; int mDocumentOffset; @@ -57,12 +63,14 @@ private: #undef SUB_RANGE_ACCESS public: - WorkflowCreationMenu() { + WorkflowCreationMenu() + { SetupCandidates(); } private: - void SetupCandidates() { + void SetupCandidates() + { // Numeric nodes offset start at 0 mCandidates.push_back(Candidate{ .Constructor = []() -> std::unique_ptr<WorkflowNode> { return std::make_unique<NumericOperationNode>(NumericOperationNode::Addition); }, @@ -127,21 +135,25 @@ private: } }; -class WorkflowUI { +class WorkflowUI +{ private: Workflow* mWorkflow; ImNodes::EditorContext* mContext; public: - WorkflowUI() { + WorkflowUI() + { mContext = ImNodes::CreateEditor(); } - ~WorkflowUI() { + ~WorkflowUI() + { ImNodes::DestroyEditor(mContext); } - void Draw() { + void Draw() + { ImNodes::SetCurrentEditor(mContext); ImNodes::Begin(""); @@ -164,7 +176,8 @@ public: }; } // namespace -void UI::WorkflowsTab() { +void UI::WorkflowsTab() +{ static std::unique_ptr<WorkflowUI> openWorkflow; // TODO } diff --git a/core/src/Utils/Enum.hpp b/core/src/Utils/Enum.hpp index e774b01..1fb9661 100644 --- a/core/src/Utils/Enum.hpp +++ b/core/src/Utils/Enum.hpp @@ -3,7 +3,8 @@ #include <compare> template <class TSelf> -struct BasicEnum { +struct BasicEnum +{ using Self = TSelf; using ValueType = int; @@ -14,24 +15,42 @@ struct BasicEnum { BasicEnum(int value) : value{ value } {} - /// Comparsion between 2 values of enum. Useful for situations like `a == b` where both a and b are TSelf. - friend auto operator<=>(const TSelf& a, const TSelf& b) { return a.value <=> b.value; } - /// Comparsion between a enum and a raw value. Useful for situations like `a == TSelf::Option` where a is a enum and TSelf::Option is a raw value. - friend auto operator<=>(const TSelf& self, int value) { return self.value <=> value; } + /// Comparison between 2 values of enum. Useful for situations like `a == b` where both a and b are TSelf. + friend auto operator<=>(const TSelf& a, const TSelf& b) + { + return a.value <=> b.value; + } + + /// Comparison between a enum and a raw value. Useful for situations like `a == TSelf::Option` where a is a enum and TSelf::Option is a raw value. + friend auto operator<=>(const TSelf& self, int value) + { + return self.value <=> value; + } - operator int() const { return value; } - operator bool() const { return value; } + operator int() const + { + return value; + } + + operator bool() const + { + return value; + } }; #define ENUM(Name) struct Name : public BasicEnum<Name> -#define ENUM_MEMBERS() \ - enum Enum : int; \ - operator Enum() const { return (Enum)value; } \ - using BasicEnum<Self>::BasicEnum; \ +#define ENUM_MEMBERS() \ + enum Enum : int; \ + operator Enum() const \ + { \ + return (Enum)value; \ + } \ + using BasicEnum<Self>::BasicEnum; \ enum Enum : int template <class TSelf> -struct BasicFlag { +struct BasicFlag +{ using Self = TSelf; using ValueType = int; @@ -42,9 +61,16 @@ struct BasicFlag { BasicFlag(int value) : value{ value } {} - bool IsSet(TSelf mask) const { return (value & mask.value) == mask.value; } - bool IsSetExclusive(TSelf mask) const { return value == mask.value; } - void Set(TSelf mask, bool state) { + bool IsSet(TSelf mask) const + { + return (value & mask.value) == mask.value; + } + bool IsSetExclusive(TSelf mask) const + { + return value == mask.value; + } + void Set(TSelf mask, bool state) + { if (state) { value = (int)(value | mask.value); } else { @@ -53,29 +79,61 @@ struct BasicFlag { } /// Comparsion between 2 values of flag. Useful for situations like `a == b` where both a and b are TSelf. - friend bool operator==(const TSelf& a, const TSelf& b) { return a.value == b.value; } - friend auto operator<=>(const TSelf& a, const TSelf& b) { return a.value <=> b.value; } + friend bool operator==(const TSelf& a, const TSelf& b) + { + return a.value == b.value; + } + + friend auto operator<=>(const TSelf& a, const TSelf& b) + { + return a.value <=> b.value; + } + /// Comparsion between a flag and a raw value. Useful for situations like `a == TSelf::Option` where a is a flag and TSelf::Option is a raw value. - friend bool operator==(const TSelf& self, int value) { return self.value == value; } - friend auto operator<=>(const TSelf& self, int value) { return self.value <=> value; } + friend bool operator==(const TSelf& self, int value) + { + return self.value == value; + } + + friend auto operator<=>(const TSelf& self, int value) + { + return self.value <=> value; + } + + friend TSelf operator&(const TSelf& a, const TSelf& b) + { + return TSelf(a.value & b.value); + } - friend TSelf operator&(const TSelf& a, const TSelf& b) { return TSelf(a.value & b.value); } - friend TSelf operator|(const TSelf& a, const TSelf& b) { return TSelf(a.value | b.value); } - friend TSelf operator^(const TSelf& a, const TSelf& b) { return TSelf(a.value ^ b.value); } + friend TSelf operator|(const TSelf& a, const TSelf& b) + { + return TSelf(a.value | b.value); + } - TSelf operator~() const { return TSelf(~value); } + friend TSelf operator^(const TSelf& a, const TSelf& b) + { + return TSelf(a.value ^ b.value); + } + + TSelf operator~() const + { + return TSelf(~value); + } - TSelf& operator&=(int that) { + TSelf& operator&=(int that) + { value = value & that; return *this; } - TSelf& operator|=(int that) { + TSelf& operator|=(int that) + { value = value | that; return *this; } - TSelf& operator^=(int that) { + TSelf& operator^=(int that) + { value = value ^ that; return *this; } diff --git a/core/src/Utils/I18n.cpp b/core/src/Utils/I18n.cpp index edc5469..e5131cc 100644 --- a/core/src/Utils/I18n.cpp +++ b/core/src/Utils/I18n.cpp @@ -14,15 +14,18 @@ using namespace std::literals::string_view_literals; namespace { -struct LanguageInfo { +struct LanguageInfo +{ std::string CodeName; std::string LocaleName; fs::path File; }; -class I18nState { +class I18nState +{ public: - static I18nState& Get() { + static I18nState& Get() + { static I18nState instance; return instance; } @@ -33,19 +36,22 @@ public: LanguageInfo* CurrentLanguage = nullptr; bool Unloaded = false; - void Unload() { + void Unload() + { Unloaded = true; CurrentEntries = {}; } - void EnsureLoaded() { + void EnsureLoaded() + { if (Unloaded) { Unloaded = false; Reload(); } } - void Reload() { + void Reload() + { if (!CurrentLanguage) return; std::ifstream ifs(CurrentLanguage->File); @@ -65,7 +71,8 @@ public: } }; -std::string FindLocalizedName(const fs::path& localeFile) { +std::string FindLocalizedName(const fs::path& localeFile) +{ std::ifstream ifs(localeFile); if (!ifs) { throw std::runtime_error("Failed to open locale file."); @@ -82,7 +89,8 @@ std::string FindLocalizedName(const fs::path& localeFile) { } // namespace -void I18n::Init() { +void I18n::Init() +{ auto& state = I18nState::Get(); auto dir = fs::current_path() / "locale"; @@ -106,7 +114,8 @@ void I18n::Init() { } } -void I18n::Shutdown() { +void I18n::Shutdown() +{ auto& state = I18nState::Get(); state.LocaleInfos.clear(); state.CurrentEntries.clear(); @@ -114,18 +123,21 @@ void I18n::Shutdown() { state.Unloaded = false; } -void I18n::Unload() { +void I18n::Unload() +{ auto& state = I18nState::Get(); state.Unload(); OnUnload(); } -std::string_view I18n::GetLanguage() { +std::string_view I18n::GetLanguage() +{ auto& state = I18nState::Get(); return state.CurrentLanguage->CodeName; } -bool I18n::SetLanguage(std::string_view lang) { +bool I18n::SetLanguage(std::string_view lang) +{ auto& state = I18nState::Get(); if (state.CurrentLanguage && state.CurrentLanguage->CodeName == lang) @@ -142,7 +154,8 @@ bool I18n::SetLanguage(std::string_view lang) { return true; } -std::optional<std::string_view> I18n::Lookup(std::string_view key) { +std::optional<std::string_view> I18n::Lookup(std::string_view key) +{ auto& state = I18nState::Get(); state.EnsureLoaded(); @@ -154,7 +167,8 @@ std::optional<std::string_view> I18n::Lookup(std::string_view key) { } } -std::string_view I18n::LookupUnwrap(std::string_view key) { +std::string_view I18n::LookupUnwrap(std::string_view key) +{ auto o = Lookup(key); if (!o) { std::string msg; @@ -166,7 +180,8 @@ std::string_view I18n::LookupUnwrap(std::string_view key) { return o.value(); } -std::string_view I18n::LookupLanguage(std::string_view lang) { +std::string_view I18n::LookupLanguage(std::string_view lang) +{ auto& state = I18nState::Get(); auto iter = state.LocaleInfos.find(lang); if (iter != state.LocaleInfos.end()) { @@ -177,18 +192,22 @@ std::string_view I18n::LookupLanguage(std::string_view lang) { } BasicTranslation::BasicTranslation(std::string_view key) - : mContent{ I18n::LookupUnwrap(key) } { + : mContent{ I18n::LookupUnwrap(key) } +{ } -const std::string& BasicTranslation::GetString() const { +const std::string& BasicTranslation::GetString() const +{ return mContent; } -const char* BasicTranslation::Get() const { +const char* BasicTranslation::Get() const +{ return mContent.c_str(); } -FormattedTranslation::FormattedTranslation(std::string_view key) { +FormattedTranslation::FormattedTranslation(std::string_view key) +{ auto src = I18n::LookupUnwrap(key); mMinimumResultLen = 0; @@ -259,7 +278,8 @@ FormattedTranslation::FormattedTranslation(std::string_view key) { } } -std::string FormattedTranslation::Format(std::span<Argument> args) { +std::string FormattedTranslation::Format(std::span<Argument> args) +{ if (args.size() != mNumArguments) { throw std::runtime_error("Invalid number of arguments for FormattedTranslation::Format, expected " + std::to_string(mNumArguments) + " but found " + std::to_string(args.size()) + "."); } diff --git a/core/src/Utils/I18n.hpp b/core/src/Utils/I18n.hpp index a4dd225..6285d60 100644 --- a/core/src/Utils/I18n.hpp +++ b/core/src/Utils/I18n.hpp @@ -11,7 +11,8 @@ #include <variant> #include <vector> -class I18n { +class I18n +{ public: static inline Signal<> OnLanguageChange{}; static inline Signal<> OnUnload{}; @@ -37,19 +38,23 @@ public: static std::string_view LookupLanguage(std::string_view lang); }; -struct StringArgument { +struct StringArgument +{ std::string Value; }; -struct IntArgument { +struct IntArgument +{ int Value; }; -struct FloatArgument { +struct FloatArgument +{ double Value; }; -class BasicTranslation { +class BasicTranslation +{ private: std::string mContent; @@ -59,7 +64,8 @@ public: const char* Get() const; }; -class FormattedTranslation { +class FormattedTranslation +{ public: using Element = std::variant<std::string, int>; using Argument = std::string; @@ -74,7 +80,8 @@ public: std::string Format(std::span<Argument> args); }; -class NumericTranslation { +class NumericTranslation +{ public: // TODO }; diff --git a/core/src/Utils/RTTI.hpp b/core/src/Utils/RTTI.hpp index bc0d289..86b1e2c 100644 --- a/core/src/Utils/RTTI.hpp +++ b/core/src/Utils/RTTI.hpp @@ -3,13 +3,15 @@ #include <cassert> template <class T, class TBase> -bool is_a(TBase* t) { +bool is_a(TBase* t) +{ assert(t != nullptr); return T::IsInstance(t); } template <class T, class TBase> -bool is_a_nullable(TBase* t) { +bool is_a_nullable(TBase* t) +{ if (t) { return is_a<T, TBase>(t); } else { @@ -18,7 +20,8 @@ bool is_a_nullable(TBase* t) { } template <class T, class TBase> -T* dyn_cast(TBase* t) { +T* dyn_cast(TBase* t) +{ assert(t != nullptr); if (T::IsInstance(t)) { return static_cast<T*>(t); @@ -28,7 +31,8 @@ T* dyn_cast(TBase* t) { } template <class T, class TBase> -const T* dyn_cast(const TBase* t) { +const T* dyn_cast(const TBase* t) +{ assert(t != nullptr); if (T::IsInstance(t)) { return static_cast<const T*>(t); @@ -38,7 +42,8 @@ const T* dyn_cast(const TBase* t) { } template <class T, class TBase> -T* dyn_cast_nullable(TBase* t) { +T* dyn_cast_nullable(TBase* t) +{ if (!t) return nullptr; return dyn_cast<T, TBase>(t); } diff --git a/core/src/Utils/ScopeGuard.hpp b/core/src/Utils/ScopeGuard.hpp index ed8d4ea..28ffd0b 100644 --- a/core/src/Utils/ScopeGuard.hpp +++ b/core/src/Utils/ScopeGuard.hpp @@ -5,7 +5,8 @@ #include <utility> template <class TCleanupFunc> -class ScopeGuard { +class ScopeGuard +{ private: TCleanupFunc mFunc; bool mDismissed = false; @@ -18,16 +19,19 @@ public: /// would work. It is highly discourage and unlikely that one would want to use ScopeGuard as a function /// parameter, so the normal argument that implicit conversion are harmful doesn't really apply here. ScopeGuard(TCleanupFunc func) - : mFunc{ std::move(func) } { + : mFunc{ std::move(func) } + { } - ~ScopeGuard() { + ~ScopeGuard() + { if (!mDismissed) { mFunc(); } } - void Dismiss() noexcept { + void Dismiss() noexcept + { mDismissed = true; } }; diff --git a/core/src/Utils/Sigslot.cpp b/core/src/Utils/Sigslot.cpp index 14deece..1132dfb 100644 --- a/core/src/Utils/Sigslot.cpp +++ b/core/src/Utils/Sigslot.cpp @@ -2,23 +2,28 @@ #include <doctest/doctest.h> -bool SignalStub::Connection::IsOccupied() const { +bool SignalStub::Connection::IsOccupied() const +{ return id != InvalidId; } SignalStub::SignalStub(IWrapper& wrapper) - : mWrapper{ &wrapper } { + : mWrapper{ &wrapper } +{ } -SignalStub::~SignalStub() { +SignalStub::~SignalStub() +{ RemoveAllConnections(); } -std::span<const SignalStub::Connection> SignalStub::GetConnections() const { +std::span<const SignalStub::Connection> SignalStub::GetConnections() const +{ return mConnections; } -SignalStub::Connection& SignalStub::InsertConnection(SlotGuard* guard) { +SignalStub::Connection& SignalStub::InsertConnection(SlotGuard* guard) +{ Connection* result; int size = static_cast<int>(mConnections.size()); for (int i = 0; i < size; ++i) { @@ -42,7 +47,8 @@ setup: return *result; } -void SignalStub::RemoveConnection(int id) { +void SignalStub::RemoveConnection(int id) +{ if (id >= 0 && id < mConnections.size()) { auto& conn = mConnections[id]; if (conn.IsOccupied()) { @@ -58,24 +64,29 @@ void SignalStub::RemoveConnection(int id) { } } -void SignalStub::RemoveConnectionFor(SlotGuard& guard) { +void SignalStub::RemoveConnectionFor(SlotGuard& guard) +{ guard.RemoveConnectionFor(*this); } -void SignalStub::RemoveAllConnections() { +void SignalStub::RemoveAllConnections() +{ for (size_t i = 0; i < mConnections.size(); ++i) { RemoveConnection(i); } } -SlotGuard::SlotGuard() { +SlotGuard::SlotGuard() +{ } -SlotGuard::~SlotGuard() { +SlotGuard::~SlotGuard() +{ DisconnectAll(); } -void SlotGuard::DisconnectAll() { +void SlotGuard::DisconnectAll() +{ for (auto& conn : mConnections) { if (conn.stub) { // Also calls SlotGuard::removeConnection, our copy of the data will be cleared in it @@ -84,7 +95,8 @@ void SlotGuard::DisconnectAll() { } } -int SlotGuard::InsertConnection(SignalStub& stub, int stubId) { +int SlotGuard::InsertConnection(SignalStub& stub, int stubId) +{ int size = static_cast<int>(mConnections.size()); for (int i = 0; i < size; ++i) { auto& conn = mConnections[i]; @@ -102,7 +114,8 @@ int SlotGuard::InsertConnection(SignalStub& stub, int stubId) { return size; } -void SlotGuard::RemoveConnectionFor(SignalStub& stub) { +void SlotGuard::RemoveConnectionFor(SignalStub& stub) +{ for (auto& conn : mConnections) { if (conn.stub == &stub) { conn.stub->RemoveConnection(conn.stubId); @@ -110,11 +123,13 @@ void SlotGuard::RemoveConnectionFor(SignalStub& stub) { } } -void SlotGuard::RemoveConnection(int slotId) { +void SlotGuard::RemoveConnection(int slotId) +{ mConnections[slotId] = {}; } -TEST_CASE("Signal connect and disconnect") { +TEST_CASE("Signal connect and disconnect") +{ Signal<> sig; int counter = 0; @@ -131,7 +146,8 @@ TEST_CASE("Signal connect and disconnect") { CHECK(counter == 2); } -TEST_CASE("Signal with parameters") { +TEST_CASE("Signal with parameters") +{ Signal<int> sig; int counter = 0; @@ -151,7 +167,8 @@ TEST_CASE("Signal with parameters") { CHECK(counter == 5); } -TEST_CASE("Signal disconnectAll()") { +TEST_CASE("Signal disconnectAll()") +{ Signal<> sig; int counter1 = 0; @@ -173,7 +190,8 @@ TEST_CASE("Signal disconnectAll()") { CHECK(counter2 == 2); } -TEST_CASE("SlotGuard auto-disconnection") { +TEST_CASE("SlotGuard auto-disconnection") +{ int counter1 = 0; int counter2 = 0; Signal<> sig; @@ -197,7 +215,8 @@ TEST_CASE("SlotGuard auto-disconnection") { CHECK(counter2 == 2); } -TEST_CASE("Signal destruct before SlotGuard") { +TEST_CASE("Signal destruct before SlotGuard") +{ int counter = 0; SlotGuard guard; diff --git a/core/src/Utils/Sigslot.hpp b/core/src/Utils/Sigslot.hpp index 2a191b4..5638f12 100644 --- a/core/src/Utils/Sigslot.hpp +++ b/core/src/Utils/Sigslot.hpp @@ -8,21 +8,25 @@ #include <utility> #include <vector> -class SignalStub { +class SignalStub +{ public: /// Non-template interface for Signal<T...> to implement (a barrier to stop template /// arguments propagation). - class IWrapper { + class IWrapper + { public: virtual ~IWrapper() = default; virtual void RemoveFunction(int id) = 0; }; - enum { + enum + { InvalidId = -1, }; - struct Connection { + struct Connection + { SlotGuard* guard; int slotId; int id = InvalidId; // If `InvalidId`, then this "spot" is unused @@ -55,7 +59,8 @@ private: }; template <class... TArgs> -class Signal : public SignalStub::IWrapper { +class Signal : public SignalStub::IWrapper +{ private: // Must be in this order so that mFunctions is still intact when mStub's destructor runs std::vector<std::function<void(TArgs...)>> mFunctions; @@ -63,7 +68,8 @@ private: public: Signal() - : mStub(*this) { + : mStub(*this) + { } virtual ~Signal() = default; @@ -73,7 +79,8 @@ public: Signal(Signal&&) = default; Signal& operator=(Signal&&) = default; - void operator()(TArgs... args) { + void operator()(TArgs... args) + { for (auto& conn : mStub.GetConnections()) { if (conn.IsOccupied()) { mFunctions[conn.id](std::forward<TArgs>(args)...); @@ -82,7 +89,8 @@ public: } template <class TFunction> - int Connect(TFunction slot) { + int Connect(TFunction slot) + { auto& conn = mStub.InsertConnection(); mFunctions.resize(std::max(mFunctions.size(), (size_t)conn.id + 1)); mFunctions[conn.id] = std::move(slot); @@ -90,26 +98,31 @@ public: } template <class TFunction> - int Connect(SlotGuard& guard, TFunction slot) { + int Connect(SlotGuard& guard, TFunction slot) + { auto& conn = mStub.InsertConnection(&guard); mFunctions.resize(std::max(mFunctions.size(), (size_t)conn.id + 1)); mFunctions[conn.id] = std::move(slot); return conn.id; } - void Disconnect(int id) { + void Disconnect(int id) + { mStub.RemoveConnection(id); } - void DisconnectFor(SlotGuard& guard) { + void DisconnectFor(SlotGuard& guard) + { mStub.RemoveConnectionFor(guard); } - void DisconnectAll() { + void DisconnectAll() + { mStub.RemoveAllConnections(); } - virtual void RemoveFunction(int id) { + virtual void RemoveFunction(int id) + { mFunctions[id] = {}; } }; @@ -117,9 +130,11 @@ public: /// Automatic disconnection mechanism for Signal<>. /// Bind connection to this guard by using the Connect(SlotGuard&, TFunction) overload. /// Either DisconnectAll() or the destructor disconnects all connections bound to this guard. -class SlotGuard { +class SlotGuard +{ private: - struct Connection { + struct Connection + { SignalStub* stub = nullptr; int stubId = SignalStub::InvalidId; }; diff --git a/core/src/Utils/StandardDirectories.cpp b/core/src/Utils/StandardDirectories.cpp index 7defc5d..e7d3657 100644 --- a/core/src/Utils/StandardDirectories.cpp +++ b/core/src/Utils/StandardDirectories.cpp @@ -12,7 +12,8 @@ namespace fs = std::filesystem; # pragma comment(lib, "shell32.lib") # pragma comment(lib, "ole32.lib") -static fs::path GetAppDataRoaming() { +static fs::path GetAppDataRoaming() +{ PWSTR path = nullptr; HRESULT hr = SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_CREATE, nullptr, &path); if (SUCCEEDED(hr)) { @@ -33,7 +34,8 @@ static fs::path GetAppDataRoaming() { #elif PLATFORM_LINUX # include <cstdlib> -static fs::path GetEnvVar(const char* name, const char* backup) { +static fs::path GetEnvVar(const char* name, const char* backup) +{ if (const char* path = std::getenv(name)) { fs::path dataDir(path); fs::create_directories(dataDir); @@ -47,7 +49,8 @@ static fs::path GetEnvVar(const char* name, const char* backup) { #endif -const std::filesystem::path& StandardDirectories::UserData() { +const std::filesystem::path& StandardDirectories::UserData() +{ static auto userDataDir = []() -> fs::path { #if PLATFORM_WIN32 return GetAppDataRoaming(); @@ -60,7 +63,8 @@ const std::filesystem::path& StandardDirectories::UserData() { return userDataDir; } -const std::filesystem::path& StandardDirectories::UserConfig() { +const std::filesystem::path& StandardDirectories::UserConfig() +{ static auto userConfigDir = []() -> fs::path { #if PLATFORM_WIN32 return GetAppDataRoaming(); diff --git a/core/src/Utils/Time.cpp b/core/src/Utils/Time.cpp index d8e0bd1..bbdc313 100644 --- a/core/src/Utils/Time.cpp +++ b/core/src/Utils/Time.cpp @@ -2,7 +2,8 @@ #include <ctime> -std::string StringifyTimePoint(std::chrono::time_point<std::chrono::system_clock> tp) { +std::string StringifyTimePoint(std::chrono::time_point<std::chrono::system_clock> tp) +{ auto t = std::chrono::system_clock::to_time_t(tp); char data[32]; @@ -14,7 +15,8 @@ std::string StringifyTimePoint(std::chrono::time_point<std::chrono::system_clock return std::string(data); } -std::string StringifyTimeStamp(int64_t timeStamp) { +std::string StringifyTimeStamp(int64_t timeStamp) +{ if (timeStamp == 0) { return ""; } diff --git a/core/src/Utils/Time.hpp b/core/src/Utils/Time.hpp index 1f5a048..13e12a1 100644 --- a/core/src/Utils/Time.hpp +++ b/core/src/Utils/Time.hpp @@ -1,7 +1,7 @@ #pragma once -#include <string> #include <chrono> +#include <string> std::string StringifyTimePoint(std::chrono::time_point<std::chrono::system_clock> tp); std::string StringifyTimeStamp(int64_t timeStamp); diff --git a/core/src/Utils/Variant.hpp b/core/src/Utils/Variant.hpp index 7fdb2dc..df2f882 100644 --- a/core/src/Utils/Variant.hpp +++ b/core/src/Utils/Variant.hpp @@ -4,16 +4,21 @@ #include <variant> template <class... Ts> -struct Overloaded : Ts... { using Ts::operator()...; }; +struct Overloaded : Ts... +{ + using Ts::operator()...; +}; template <class... Ts> Overloaded(Ts...) -> Overloaded<Ts...>; template <class... Args> -struct VariantCastProxy { +struct VariantCastProxy +{ std::variant<Args...> v; template <class... ToArgs> - operator std::variant<ToArgs...>() const { + operator std::variant<ToArgs...>() const + { return std::visit( [](auto&& arg) -> std::variant<ToArgs...> { return arg; }, v); @@ -22,6 +27,7 @@ struct VariantCastProxy { /// Use snake_case naming to align with `static_cast`, `dynamic_cast`, etc.. template <class... Args> -auto variant_cast(std::variant<Args...> v) -> VariantCastProxy<Args...> { +auto variant_cast(std::variant<Args...> v) -> VariantCastProxy<Args...> +{ return { std::move(v) }; } diff --git a/core/src/Utils/Vector.hpp b/core/src/Utils/Vector.hpp index 372d484..61fa520 100644 --- a/core/src/Utils/Vector.hpp +++ b/core/src/Utils/Vector.hpp @@ -1,6 +1,7 @@ #pragma once -struct Vec2i { +struct Vec2i +{ int x = 0; int y = 0; }; |