aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt14
-rw-r--r--src/application.cpp113
-rw-r--r--src/base.hpp39
-rw-r--r--src/cru_debug.cpp11
-rw-r--r--src/cru_debug.hpp50
-rw-r--r--src/exception.cpp42
-rw-r--r--src/exception.hpp52
-rw-r--r--src/platform_win/CMakeLists.txt10
-rw-r--r--src/platform_win/debug.cpp10
-rw-r--r--src/platform_win/exception.cpp50
-rw-r--r--src/platform_win/god_window.cpp70
-rw-r--r--src/platform_win/god_window_message.hpp6
-rw-r--r--src/platform_win/timer.cpp28
-rw-r--r--src/platform_win/timer.hpp34
-rw-r--r--src/platform_win/win_application.cpp70
-rw-r--r--src/platform_win/window_class.cpp (renamed from src/ui/window_class.cpp)8
-rw-r--r--src/pre.hpp14
-rw-r--r--src/timer.cpp52
-rw-r--r--src/timer.hpp64
-rw-r--r--src/ui/ui_base.hpp238
-rw-r--r--src/ui/window_class.hpp26
-rw-r--r--src/util/format.hpp100
22 files changed, 287 insertions, 814 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b89e5202..5048020d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,8 +1,4 @@
add_library(cru_ui STATIC
- application.cpp
- cru_debug.cpp
- exception.cpp
- timer.cpp
graph/graph_manager.cpp
graph/window_render_target.cpp
ui/content_control.cpp
@@ -11,7 +7,6 @@ add_library(cru_ui STATIC
ui/layout_control.cpp
ui/no_child_control.cpp
ui/ui_manager.cpp
- ui/window_class.cpp
ui/window.cpp
ui/controls/button.cpp
ui/controls/flex_layout.cpp
@@ -23,14 +18,15 @@ add_library(cru_ui STATIC
ui/render/window_render_object.cpp
util/string_util.cpp)
-
-target_include_directories(cru_ui PUBLIC .)
+target_include_directories(cru_ui PUBLIC ${PROJECT_SOURCE_DIR}/include .)
if(WIN32)
-target_link_libraries(cru_ui PRIVATE D3D11 D2d1 DWrite)
-target_compile_definitions(cru_ui PUBLIC UNICODE _UNICODE) # use unicode
+add_subdirectory(platform_win)
+target_link_libraries(cru_ui PUBLIC cru_platform_win)
endif()
+
+
add_executable(demo WIN32 main.cpp)
target_link_libraries(demo PRIVATE cru_ui)
diff --git a/src/application.cpp b/src/application.cpp
deleted file mode 100644
index aafca6fe..00000000
--- a/src/application.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-#include "application.hpp"
-
-#include <VersionHelpers.h>
-
-#include "exception.hpp"
-#include "timer.hpp"
-#include "ui/window_class.hpp"
-
-namespace cru {
-constexpr auto god_window_class_name = L"GodWindowClass";
-constexpr int invoke_later_message_id = WM_USER + 2000;
-
-LRESULT CALLBACK GodWndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
- LPARAM lParam) {
- const auto app = Application::GetInstance();
-
- if (app) {
- const auto result =
- app->GetGodWindow()->HandleGodWindowMessage(hWnd, uMsg, wParam, lParam);
- if (result.has_value())
- return result.value();
- else
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
- } else
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
-}
-
-GodWindow::GodWindow(Application* application) {
- const auto h_instance = application->GetInstanceHandle();
-
- god_window_class_ = std::make_unique<ui::WindowClass>(god_window_class_name,
- GodWndProc, h_instance);
-
- hwnd_ = CreateWindowEx(0, god_window_class_name, L"", 0, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
- HWND_MESSAGE, nullptr, h_instance, nullptr);
-
- if (hwnd_ == nullptr) throw std::runtime_error("Failed to create window.");
-}
-
-GodWindow::~GodWindow() { ::DestroyWindow(hwnd_); }
-
-std::optional<LRESULT> GodWindow::HandleGodWindowMessage(HWND hwnd, int msg,
- WPARAM w_param,
- LPARAM l_param) {
- switch (msg) {
- case invoke_later_message_id: {
- const auto p_action = reinterpret_cast<std::function<void()>*>(w_param);
- (*p_action)();
- delete p_action;
- return 0;
- }
- case WM_TIMER: {
- const auto id = static_cast<UINT_PTR>(w_param);
- const auto action = TimerManager::GetInstance()->GetAction(id);
- if (action.has_value()) {
- (action.value().second)();
- if (!action.value().first) TimerManager::GetInstance()->KillTimer(id);
- return 0;
- }
- break;
- }
- default:
- return std::nullopt;
- }
- return std::nullopt;
-}
-
-Application* Application::instance_ = nullptr;
-
-Application* Application::GetInstance() { return instance_; }
-
-Application::Application(HINSTANCE h_instance) : h_instance_(h_instance) {
- if (instance_)
- throw std::runtime_error("A application instance already exists.");
-
- instance_ = this;
-
- if (!::IsWindows8OrGreater())
- throw std::runtime_error("Must run on Windows 8 or later.");
-
- god_window_ = std::make_unique<GodWindow>(this);
-}
-
-Application::~Application() {
- for (auto i = singleton_list_.crbegin(); i != singleton_list_.crend(); ++i)
- delete *i;
- instance_ = nullptr;
-}
-
-int Application::Run() {
- MSG msg;
-
- while (GetMessage(&msg, nullptr, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- return static_cast<int>(msg.wParam);
-}
-
-void Application::Quit(const int quit_code) { ::PostQuitMessage(quit_code); }
-
-void InvokeLater(const std::function<void()>& action) {
- // copy the action to a safe place
- auto p_action_copy = new std::function<void()>(action);
-
- if (PostMessageW(Application::GetInstance()->GetGodWindow()->GetHandle(),
- invoke_later_message_id,
- reinterpret_cast<WPARAM>(p_action_copy), 0) == 0)
- throw Win32Error(::GetLastError(), "InvokeLater failed to post message.");
-}
-} // namespace cru
diff --git a/src/base.hpp b/src/base.hpp
deleted file mode 100644
index e3dfc1ee..00000000
--- a/src/base.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-#include "pre.hpp"
-
-#include <cassert>
-#include <chrono>
-#include <stdexcept>
-#include <string>
-#include <string_view>
-
-namespace cru {
-// typedefs
-using String = std::wstring;
-using MultiByteString = std::string;
-
-using StringView = std::wstring_view;
-using MultiByteStringView = std::string_view;
-
-using FloatSecond = std::chrono::duration<double, std::chrono::seconds::period>;
-
-enum class FlowControl { Continue, Break };
-
-class Object {
- public:
- Object() = default;
- Object(const Object&) = default;
- Object& operator=(const Object&) = default;
- Object(Object&&) = default;
- Object& operator=(Object&&) = default;
- virtual ~Object() = default;
-};
-
-struct Interface {
- virtual ~Interface() = default;
-};
-
-[[noreturn]] inline void UnreachableCode() {
- throw std::logic_error("Unreachable code.");
-}
-} // namespace cru
diff --git a/src/cru_debug.cpp b/src/cru_debug.cpp
deleted file mode 100644
index 81945227..00000000
--- a/src/cru_debug.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "cru_debug.hpp"
-
-#include <Windows.h>
-
-namespace cru::debug {
-#ifdef CRU_DEBUG
-void DebugMessage(const StringView& message) {
- ::OutputDebugStringW(message.data());
-}
-#endif
-} // namespace cru::debug
diff --git a/src/cru_debug.hpp b/src/cru_debug.hpp
deleted file mode 100644
index 58431d56..00000000
--- a/src/cru_debug.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#pragma once
-#include "pre.hpp"
-
-#include <functional>
-
-#include "base.hpp"
-#include "util/format.hpp"
-
-namespace cru::debug {
-#ifdef CRU_DEBUG
-void DebugMessage(const StringView& message);
-#else
-inline void DebugMessage(const StringView& message) {}
-#endif
-
-#ifdef CRU_DEBUG
-inline void DebugTime(const std::function<void()>& action,
- const StringView& hint_message) {
- const auto before = std::chrono::steady_clock::now();
- action();
- const auto after = std::chrono::steady_clock::now();
- const auto duration =
- std::chrono::duration_cast<std::chrono::milliseconds>(after - before);
- DebugMessage(util::Format(L"{}: {}ms.\n", hint_message, duration.count()));
-}
-
-template <typename TReturn>
-TReturn DebugTime(const std::function<TReturn()>& action,
- const StringView& hint_message) {
- const auto before = std::chrono::steady_clock::now();
- auto&& result = action();
- const auto after = std::chrono::steady_clock::now();
- const auto duration =
- std::chrono::duration_cast<std::chrono::milliseconds>(after - before);
- DebugMessage(util::Format(L"{}: {}ms.\n", hint_message, duration.count()));
- return std::move(result);
-}
-#else
-inline void DebugTime(const std::function<void()>& action,
- const StringView& hint_message) {
- action();
-}
-
-template <typename TReturn>
-TReturn DebugTime(const std::function<TReturn()>& action,
- const StringView& hint_message) {
- return action();
-}
-#endif
-} // namespace cru::debug
diff --git a/src/exception.cpp b/src/exception.cpp
deleted file mode 100644
index dbc98453..00000000
--- a/src/exception.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "exception.hpp"
-
-#include "util/format.hpp"
-
-namespace cru {
-using util::Format;
-
-inline std::string HResultMakeMessage(
- HRESULT h_result, std::optional<MultiByteStringView> message) {
- char buffer[10];
- sprintf_s(buffer, "%#08x", h_result);
-
- if (message.has_value())
- return Format(
- "An HResultError is thrown. HRESULT: {}.\nAdditional message: {}\n",
- buffer, message.value());
- else
- return Format("An HResultError is thrown. HRESULT: {}.\n", buffer);
-}
-
-HResultError::HResultError(
- HRESULT h_result, std::optional<MultiByteStringView> additional_message)
- : runtime_error(HResultMakeMessage(h_result, std::nullopt)),
- h_result_(h_result) {}
-
-inline std::string Win32MakeMessage(
- DWORD error_code, std::optional<MultiByteStringView> message) {
- char buffer[10];
- sprintf_s(buffer, "%#04x", error_code);
-
- if (message.has_value())
- return Format("Last error code: {}.\nAdditional message: {}\n", buffer,
- message.value());
- else
- return Format("Last error code: {}.\n", buffer);
-}
-
-Win32Error::Win32Error(DWORD error_code,
- std::optional<MultiByteStringView> additional_message)
- : runtime_error(Win32MakeMessage(error_code, std::nullopt)),
- error_code_(error_code) {}
-} // namespace cru
diff --git a/src/exception.hpp b/src/exception.hpp
deleted file mode 100644
index ade51d54..00000000
--- a/src/exception.hpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-#include "pre.hpp"
-
-#include <Windows.h>
-#include <optional>
-
-#include "base.hpp"
-
-namespace cru {
-class HResultError : public std::runtime_error {
- public:
- explicit HResultError(
- HRESULT h_result,
- std::optional<MultiByteStringView> additional_message = std::nullopt);
- HResultError(const HResultError& other) = default;
- HResultError(HResultError&& other) = default;
- HResultError& operator=(const HResultError& other) = default;
- HResultError& operator=(HResultError&& other) = default;
- ~HResultError() override = default;
-
- HRESULT GetHResult() const { return h_result_; }
-
- private:
- HRESULT h_result_;
-};
-
-inline void ThrowIfFailed(const HRESULT h_result) {
- if (FAILED(h_result)) throw HResultError(h_result);
-}
-
-inline void ThrowIfFailed(const HRESULT h_result,
- const MultiByteStringView& message) {
- if (FAILED(h_result)) throw HResultError(h_result, message);
-}
-
-class Win32Error : public std::runtime_error {
- public:
- explicit Win32Error(
- DWORD error_code,
- std::optional<MultiByteStringView> additional_message = std::nullopt);
- Win32Error(const Win32Error& other) = default;
- Win32Error(Win32Error&& other) = default;
- Win32Error& operator=(const Win32Error& other) = default;
- Win32Error& operator=(Win32Error&& other) = default;
- ~Win32Error() override = default;
-
- HRESULT GetErrorCode() const { return error_code_; }
-
- private:
- DWORD error_code_;
-};
-} // namespace cru
diff --git a/src/platform_win/CMakeLists.txt b/src/platform_win/CMakeLists.txt
new file mode 100644
index 00000000..fbcf1c00
--- /dev/null
+++ b/src/platform_win/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_library(cru_platform_win STATIC
+ debug.cpp
+ exception.cpp
+ god_window.cpp
+ timer.cpp
+ win_application.cpp
+ window_class.cpp)
+target_include_directories(cru_platform_win PUBLIC ${PROJECT_SOURCE_DIR}/include .)
+target_link_libraries(cru_platform_win PRIVATE D3D11 D2d1 DWrite)
+target_compile_definitions(cru_platform_win PUBLIC UNICODE _UNICODE) # use unicode
diff --git a/src/platform_win/debug.cpp b/src/platform_win/debug.cpp
new file mode 100644
index 00000000..cdff7963
--- /dev/null
+++ b/src/platform_win/debug.cpp
@@ -0,0 +1,10 @@
+#include "cru/platform/win/win_pre_config.hpp"
+
+#include "cru/platform/debug.hpp"
+
+
+namespace cru::debug {
+void DebugMessage(const std::wstring_view& message) {
+ ::OutputDebugStringW(message.data());
+}
+} // namespace cru::debug
diff --git a/src/platform_win/exception.cpp b/src/platform_win/exception.cpp
new file mode 100644
index 00000000..3db88b8b
--- /dev/null
+++ b/src/platform_win/exception.cpp
@@ -0,0 +1,50 @@
+#include "cru/platform/win/exception.hpp"
+
+#include "cru/common/format.hpp"
+
+namespace cru::platform::win {
+using util::Format;
+
+inline std::string HResultMakeMessage(HRESULT h_result,
+ const std::string_view* message) {
+ char buffer[10];
+ sprintf_s(buffer, "%#08x", h_result);
+
+ if (message)
+ return Format(
+ "An HResultError is thrown. HRESULT: {}.\nAdditional message: {}\n",
+ buffer, *message);
+ else
+ return Format("An HResultError is thrown. HRESULT: {}.\n", buffer);
+}
+
+HResultError::HResultError(HRESULT h_result)
+ : runtime_error(HResultMakeMessage(h_result, nullptr)),
+ h_result_(h_result) {}
+
+HResultError::HResultError(HRESULT h_result,
+ const std::string_view& additional_message)
+ : runtime_error(HResultMakeMessage(h_result, &additional_message)),
+ h_result_(h_result) {}
+
+inline std::string Win32MakeMessage(DWORD error_code,
+ const std::string_view* message) {
+ char buffer[10];
+ sprintf_s(buffer, "%#04x", error_code);
+
+ if (message)
+ return Format("Last error code: {}.\nAdditional message: {}\n", buffer,
+ *message);
+ else
+ return Format("Last error code: {}.\n", buffer);
+}
+
+Win32Error::Win32Error(DWORD error_code)
+ : runtime_error(Win32MakeMessage(error_code, nullptr)),
+ error_code_(error_code) {}
+
+Win32Error::Win32Error(DWORD error_code,
+ const std::string_view& additional_message)
+ : runtime_error(Win32MakeMessage(error_code, &additional_message)),
+ error_code_(error_code) {}
+} // namespace cru::platform::win
diff --git a/src/platform_win/god_window.cpp b/src/platform_win/god_window.cpp
new file mode 100644
index 00000000..2b4fbe48
--- /dev/null
+++ b/src/platform_win/god_window.cpp
@@ -0,0 +1,70 @@
+#include "cru/platform/win/god_window.hpp"
+
+#include "cru/platform/win/exception.hpp"
+#include "cru/platform/win/win_application.hpp"
+#include "cru/platform/win/window_class.hpp"
+#include "god_window_message.hpp"
+#include "timer.hpp"
+
+namespace cru::platform::win {
+constexpr auto god_window_class_name = L"GodWindowClass";
+
+LRESULT CALLBACK GodWndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam) {
+ const auto app = WinApplication::GetInstance();
+
+ if (app) {
+ const auto result =
+ app->GetGodWindow()->HandleGodWindowMessage(hWnd, uMsg, wParam, lParam);
+ if (result.has_value())
+ return result.value();
+ else
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+ } else
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+}
+
+GodWindow::GodWindow(WinApplication* application) {
+ application_ = application;
+
+ const auto h_instance = application->GetInstanceHandle();
+
+ god_window_class_ = std::make_shared<WindowClass>(god_window_class_name,
+ GodWndProc, h_instance);
+
+ hwnd_ = CreateWindowEx(0, god_window_class_name, L"", 0, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ HWND_MESSAGE, nullptr, h_instance, nullptr);
+
+ if (hwnd_ == nullptr) throw Win32Error(::GetLastError(), "Failed to create god window.");
+}
+
+GodWindow::~GodWindow() { ::DestroyWindow(hwnd_); }
+
+std::optional<LRESULT> GodWindow::HandleGodWindowMessage(HWND hwnd, int msg,
+ WPARAM w_param,
+ LPARAM l_param) {
+ switch (msg) {
+ case invoke_later_message_id: {
+ const auto p_action = reinterpret_cast<std::function<void()>*>(w_param);
+ (*p_action)();
+ delete p_action;
+ return 0;
+ }
+ case WM_TIMER: {
+ const auto id = static_cast<UINT_PTR>(w_param);
+ const auto action = application_->GetTimerManager()->GetAction(id);
+ if (action.has_value()) {
+ (action.value().second)();
+ if (!action.value().first)
+ application_->GetTimerManager()->KillTimer(id);
+ return 0;
+ }
+ break;
+ }
+ default:
+ return std::nullopt;
+ }
+ return std::nullopt;
+}
+} // namespace cru::platform::win \ No newline at end of file
diff --git a/src/platform_win/god_window_message.hpp b/src/platform_win/god_window_message.hpp
new file mode 100644
index 00000000..a906a3b7
--- /dev/null
+++ b/src/platform_win/god_window_message.hpp
@@ -0,0 +1,6 @@
+#pragma once
+#include "cru/platform/win/win_pre_config.hpp"
+
+namespace cru::platform::win {
+constexpr int invoke_later_message_id = WM_USER + 2000;
+}
diff --git a/src/platform_win/timer.cpp b/src/platform_win/timer.cpp
new file mode 100644
index 00000000..280d1aed
--- /dev/null
+++ b/src/platform_win/timer.cpp
@@ -0,0 +1,28 @@
+#include "timer.hpp"
+
+namespace cru::platform::win {
+TimerManager::TimerManager(GodWindow* god_window) { god_window_ = god_window; }
+
+UINT_PTR TimerManager::CreateTimer(const UINT milliseconds, const bool loop,
+ const TimerAction& action) {
+ const auto id = current_count_++;
+ ::SetTimer(god_window_->GetHandle(), id, milliseconds, nullptr);
+ map_.emplace(id, std::make_pair(loop, action));
+ return id;
+}
+
+void TimerManager::KillTimer(const UINT_PTR id) {
+ const auto find_result = map_.find(id);
+ if (find_result != map_.cend()) {
+ ::KillTimer(god_window_->GetHandle(), id);
+ map_.erase(find_result);
+ }
+}
+
+std::optional<std::pair<bool, TimerAction>> TimerManager::GetAction(
+ const UINT_PTR id) {
+ const auto find_result = map_.find(id);
+ if (find_result == map_.cend()) return std::nullopt;
+ return find_result->second;
+}
+} // namespace cru::platform::win
diff --git a/src/platform_win/timer.hpp b/src/platform_win/timer.hpp
new file mode 100644
index 00000000..95468b8d
--- /dev/null
+++ b/src/platform_win/timer.hpp
@@ -0,0 +1,34 @@
+#pragma once
+#include "cru/platform/win/win_pre_config.hpp"
+
+#include <chrono>
+#include <functional>
+#include <map>
+#include <optional>
+
+#include "cru/common/base.hpp"
+#include "cru/platform/win/god_window.hpp"
+
+namespace cru::platform::win {
+using TimerAction = std::function<void()>;
+
+class TimerManager : public Object {
+ public:
+ TimerManager(GodWindow* god_window);
+ TimerManager(const TimerManager& other) = delete;
+ TimerManager(TimerManager&& other) = delete;
+ TimerManager& operator=(const TimerManager& other) = delete;
+ TimerManager& operator=(TimerManager&& other) = delete;
+ ~TimerManager() override = default;
+
+ UINT_PTR CreateTimer(UINT milliseconds, bool loop, const TimerAction& action);
+ void KillTimer(UINT_PTR id);
+ std::optional<std::pair<bool, TimerAction>> GetAction(UINT_PTR id);
+
+ private:
+ GodWindow* god_window_;
+
+ std::map<UINT_PTR, std::pair<bool, TimerAction>> map_{};
+ UINT_PTR current_count_ = 0;
+};
+} // namespace cru::platform::win
diff --git a/src/platform_win/win_application.cpp b/src/platform_win/win_application.cpp
new file mode 100644
index 00000000..a90f509c
--- /dev/null
+++ b/src/platform_win/win_application.cpp
@@ -0,0 +1,70 @@
+#include "cru/platform/win/win_application.hpp"
+
+#include <VersionHelpers.h>
+
+#include "cru/platform/win/exception.hpp"
+#include "cru/platform/win/god_window.hpp"
+#include "god_window_message.hpp"
+#include "timer.hpp"
+
+namespace cru::platform::win {
+WinApplication* WinApplication::instance_ = nullptr;
+
+WinApplication* WinApplication::GetInstance() {
+ if (instance_ == nullptr)
+ instance_ = new WinApplication(::GetModuleHandleW(nullptr));
+ return instance_;
+}
+
+WinApplication::WinApplication(HINSTANCE h_instance) : h_instance_(h_instance) {
+ if (instance_)
+ throw std::runtime_error("A application instance already exists.");
+
+ instance_ = this;
+
+ if (!::IsWindows8OrGreater())
+ throw std::runtime_error("Must run on Windows 8 or later.");
+
+ god_window_ = std::make_shared<GodWindow>(this);
+ timer_manager_ = std::make_shared<TimerManager>(god_window_.get());
+}
+
+WinApplication::~WinApplication() { instance_ = nullptr; }
+
+int WinApplication::Run() {
+ MSG msg;
+ while (GetMessageW(&msg, nullptr, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+ return static_cast<int>(msg.wParam);
+}
+
+void WinApplication::Quit(const int quit_code) { ::PostQuitMessage(quit_code); }
+
+void WinApplication::InvokeLater(const std::function<void()>& action) {
+ // copy the action to a safe place
+ auto p_action_copy = new std::function<void()>(action);
+
+ if (PostMessageW(GetGodWindow()->GetHandle(), invoke_later_message_id,
+ reinterpret_cast<WPARAM>(p_action_copy), 0) == 0)
+ throw Win32Error(::GetLastError(), "InvokeLater failed to post message.");
+}
+
+unsigned long WinApplication::SetTimeout(std::chrono::milliseconds milliseconds,
+ const std::function<void()>& action) {
+ return static_cast<unsigned long>(timer_manager_->CreateTimer(
+ static_cast<UINT>(milliseconds.count()), false, action));
+}
+
+unsigned long WinApplication::SetInterval(
+ std::chrono::milliseconds milliseconds,
+ const std::function<void()>& action) {
+ return static_cast<unsigned long>(timer_manager_->CreateTimer(
+ static_cast<UINT>(milliseconds.count()), true, action));
+}
+
+void WinApplication::CancelTimer(unsigned long id) {
+ timer_manager_->KillTimer(static_cast<UINT_PTR>(id));
+}
+} // namespace cru::platform::win
diff --git a/src/ui/window_class.cpp b/src/platform_win/window_class.cpp
index 5e8b3454..b58f53b2 100644
--- a/src/ui/window_class.cpp
+++ b/src/platform_win/window_class.cpp
@@ -1,9 +1,9 @@
-#include "window_class.hpp"
+#include "cru/platform/win/window_class.hpp"
-#include "exception.hpp"
+#include "cru/platform/win/exception.hpp"
-namespace cru::ui {
-WindowClass::WindowClass(const String& name, WNDPROC window_proc,
+namespace cru::platform::win {
+WindowClass::WindowClass(const std::wstring& name, WNDPROC window_proc,
HINSTANCE h_instance)
: name_(name) {
WNDCLASSEX window_class;
diff --git a/src/pre.hpp b/src/pre.hpp
deleted file mode 100644
index eefc828d..00000000
--- a/src/pre.hpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-
-#ifdef _DEBUG
-#define CRU_DEBUG
-#endif
-
-#define NOMINMAX
-#define WIN32_LEAN_AND_MEAN
-
-#ifdef CRU_DEBUG
-#define _CRTDBG_MAP_ALLOC
-#include <crtdbg.h>
-#include <cstdlib>
-#endif
diff --git a/src/timer.cpp b/src/timer.cpp
deleted file mode 100644
index 40e32640..00000000
--- a/src/timer.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#include "timer.hpp"
-
-#include "application.hpp"
-
-namespace cru {
-TimerManager* TimerManager::GetInstance() {
- return Application::GetInstance()->ResolveSingleton<TimerManager>(
- [](auto) { return new TimerManager{}; });
-}
-
-UINT_PTR TimerManager::CreateTimer(const UINT milliseconds, const bool loop,
- const TimerAction& action) {
- const auto id = current_count_++;
- ::SetTimer(Application::GetInstance()->GetGodWindow()->GetHandle(), id,
- milliseconds, nullptr);
- map_.emplace(id, std::make_pair(loop, action));
- return id;
-}
-
-void TimerManager::KillTimer(const UINT_PTR id) {
- const auto find_result = map_.find(id);
- if (find_result != map_.cend()) {
- ::KillTimer(Application::GetInstance()->GetGodWindow()->GetHandle(), id);
- map_.erase(find_result);
- }
-}
-
-std::optional<std::pair<bool, TimerAction>> TimerManager::GetAction(
- const UINT_PTR id) {
- const auto find_result = map_.find(id);
- if (find_result == map_.cend()) return std::nullopt;
- return find_result->second;
-}
-
-TimerTask::TimerTask(const UINT_PTR id) : id_(id) {}
-
-void TimerTask::Cancel() const { TimerManager::GetInstance()->KillTimer(id_); }
-
-TimerTask SetTimeout(std::chrono::milliseconds milliseconds,
- const TimerAction& action) {
- const auto id = TimerManager::GetInstance()->CreateTimer(
- static_cast<UINT>(milliseconds.count()), false, action);
- return TimerTask(id);
-}
-
-TimerTask SetInterval(std::chrono::milliseconds milliseconds,
- const TimerAction& action) {
- const auto id = TimerManager::GetInstance()->CreateTimer(
- static_cast<UINT>(milliseconds.count()), true, action);
- return TimerTask(id);
-}
-} // namespace cru
diff --git a/src/timer.hpp b/src/timer.hpp
deleted file mode 100644
index 7199adc2..00000000
--- a/src/timer.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#pragma once
-#include "pre.hpp"
-
-#include <Windows.h>
-#include <chrono>
-#include <functional>
-#include <map>
-#include <optional>
-
-#include "base.hpp"
-
-namespace cru {
-using TimerAction = std::function<void()>;
-
-class TimerManager : public Object {
- public:
- static TimerManager* GetInstance();
-
- private:
- TimerManager() = default;
-
- public:
- TimerManager(const TimerManager& other) = delete;
- TimerManager(TimerManager&& other) = delete;
- TimerManager& operator=(const TimerManager& other) = delete;
- TimerManager& operator=(TimerManager&& other) = delete;
- ~TimerManager() override = default;
-
- UINT_PTR CreateTimer(UINT milliseconds, bool loop, const TimerAction& action);
- void KillTimer(UINT_PTR id);
- std::optional<std::pair<bool, TimerAction>> GetAction(UINT_PTR id);
-
- private:
- std::map<UINT_PTR, std::pair<bool, TimerAction>> map_{};
- UINT_PTR current_count_ = 0;
-};
-
-class TimerTask {
- friend TimerTask SetTimeout(std::chrono::milliseconds milliseconds,
- const TimerAction& action);
- friend TimerTask SetInterval(std::chrono::milliseconds milliseconds,
- const TimerAction& action);
-
- private:
- explicit TimerTask(UINT_PTR id);
-
- public:
- TimerTask(const TimerTask& other) = default;
- TimerTask(TimerTask&& other) = default;
- TimerTask& operator=(const TimerTask& other) = default;
- TimerTask& operator=(TimerTask&& other) = default;
- ~TimerTask() = default;
-
- void Cancel() const;
-
- private:
- UINT_PTR id_;
-};
-
-TimerTask SetTimeout(std::chrono::milliseconds milliseconds,
- const TimerAction& action);
-TimerTask SetInterval(std::chrono::milliseconds milliseconds,
- const TimerAction& action);
-} // namespace cru
diff --git a/src/ui/ui_base.hpp b/src/ui/ui_base.hpp
deleted file mode 100644
index ba6c8b9a..00000000
--- a/src/ui/ui_base.hpp
+++ /dev/null
@@ -1,238 +0,0 @@
-#pragma once
-#include "pre.hpp"
-
-#include <optional>
-
-namespace cru::ui {
-struct Point final {
- constexpr static Point Zero() { return Point(0, 0); }
-
- constexpr Point() = default;
- constexpr Point(const float x, const float y) : x(x), y(y) {}
-
- float x = 0;
- float y = 0;
-};
-
-constexpr bool operator==(const Point& left, const Point& right) {
- return left.x == right.x && left.y == right.y;
-}
-
-constexpr bool operator!=(const Point& left, const Point& right) {
- return !(left == right);
-}
-
-struct Size final {
- constexpr static Size Zero() { return Size(0, 0); }
-
- constexpr Size() = default;
- constexpr Size(const float width, const float height)
- : width(width), height(height) {}
-
- float width = 0;
- float height = 0;
-};
-
-constexpr Size operator+(const Size& left, const Size& right) {
- return Size(left.width + right.width, left.height + right.height);
-}
-
-constexpr Size operator-(const Size& left, const Size& right) {
- return Size(left.width - right.width, left.height - right.height);
-}
-
-constexpr bool operator==(const Size& left, const Size& right) {
- return left.width == right.width && left.height == right.height;
-}
-
-constexpr bool operator!=(const Size& left, const Size& right) {
- return !(left == right);
-}
-
-struct Thickness final {
- constexpr static Thickness Zero() { return Thickness(0); }
-
- constexpr Thickness() : Thickness(0) {}
-
- constexpr explicit Thickness(const float width)
- : left(width), top(width), right(width), bottom(width) {}
-
- constexpr explicit Thickness(const float horizontal, const float vertical)
- : left(horizontal), top(vertical), right(horizontal), bottom(vertical) {}
-
- constexpr Thickness(const float left, const float top, const float right,
- const float bottom)
- : left(left), top(top), right(right), bottom(bottom) {}
-
- float GetHorizontalTotal() const { return left + right; }
-
- float GetVerticalTotal() const { return top + bottom; }
-
- void SetLeftRight(const float value) { left = right = value; }
-
- void SetTopBottom(const float value) { top = bottom = value; }
-
- void SetAll(const float value) { left = top = right = bottom = value; }
-
- float Validate() const {
- return left >= 0.0 && top >= 0.0 && right >= 0.0 && bottom >= 0.0;
- }
-
- float left;
- float top;
- float right;
- float bottom;
-};
-
-constexpr bool operator==(const Thickness& left, const Thickness& right) {
- return left.left == right.left && left.top == right.top &&
- left.right == right.right && left.bottom == right.bottom;
-}
-
-constexpr bool operator!=(const Thickness& left, const Thickness& right) {
- return !(left == right);
-}
-
-struct Rect final {
- constexpr Rect() = default;
- constexpr Rect(const float left, const float top, const float width,
- const float height)
- : left(left), top(top), width(width), height(height) {}
- constexpr Rect(const Point& lefttop, const Size& size)
- : left(lefttop.x),
- top(lefttop.y),
- width(size.width),
- height(size.height) {}
-
- constexpr static Rect FromVertices(const float left, const float top,
- const float right, const float bottom) {
- return Rect(left, top, right - left, bottom - top);
- }
-
- constexpr static Rect FromCenter(const Point& center, const float width,
- const float height) {
- return Rect(center.x - width / 2.0f, center.y - height / 2.0f, width,
- height);
- }
-
- constexpr float GetRight() const { return left + width; }
-
- constexpr float GetBottom() const { return top + height; }
-
- constexpr Point GetLeftTop() const { return Point(left, top); }
-
- constexpr Point GetRightBottom() const {
- return Point(left + width, top + height);
- }
-
- constexpr Point GetLeftBottom() const { return Point(left, top + height); }
-
- constexpr Point GetRightTop() const { return Point(left + width, top); }
-
- constexpr Point GetCenter() const {
- return Point(left + width / 2.0f, top + height / 2.0f);
- }
-
- constexpr Size GetSize() const { return Size(width, height); }
-
- constexpr Rect Shrink(const Thickness& thickness) const {
- return Rect(left + thickness.left, top + thickness.top,
- width - thickness.GetHorizontalTotal(),
- height - thickness.GetVerticalTotal());
- }
-
- constexpr bool IsPointInside(const Point& point) const {
- return point.x >= left && point.x < GetRight() && point.y >= top &&
- point.y < GetBottom();
- }
-
- float left = 0.0f;
- float top = 0.0f;
- float width = 0.0f;
- float height = 0.0f;
-};
-
-constexpr bool operator==(const Rect& left, const Rect& right) {
- return left.left == right.left && left.top == right.top &&
- left.width == right.width && left.height == right.height;
-}
-
-constexpr bool operator!=(const Rect& left, const Rect& right) {
- return !(left == right);
-}
-
-struct RoundedRect final {
- constexpr RoundedRect() = default;
- constexpr RoundedRect(const Rect& rect, const float radius_x,
- const float radius_y)
- : rect(rect), radius_x(radius_x), radius_y(radius_y) {}
-
- Rect rect{};
- float radius_x = 0.0f;
- float radius_y = 0.0f;
-};
-
-constexpr bool operator==(const RoundedRect& left, const RoundedRect& right) {
- return left.rect == right.rect && left.radius_x == right.radius_x &&
- left.radius_y == right.radius_y;
-}
-
-constexpr bool operator!=(const RoundedRect& left, const RoundedRect& right) {
- return !(left == right);
-}
-
-struct Ellipse final {
- constexpr Ellipse() = default;
- constexpr Ellipse(const Point& center, const float radius_x,
- const float radius_y)
- : center(center), radius_x(radius_x), radius_y(radius_y) {}
-
- constexpr static Ellipse FromRect(const Rect& rect) {
- return Ellipse(rect.GetCenter(), rect.width / 2.0f, rect.height / 2.0f);
- }
-
- constexpr Rect GetBoundRect() const {
- return Rect::FromCenter(center, radius_x * 2.0f, radius_y * 2.0f);
- }
-
- Point center{};
- float radius_x = 0.0f;
- float radius_y = 0.0f;
-};
-
-constexpr bool operator==(const Ellipse& left, const Ellipse& right) {
- return left.center == right.center && left.radius_x == right.radius_x &&
- left.radius_y == right.radius_y;
-}
-
-constexpr bool operator!=(const Ellipse& left, const Ellipse& right) {
- return !(left == right);
-}
-
-struct TextRange final {
- constexpr static std::optional<TextRange> FromTwoSides(unsigned first,
- unsigned second) {
- if (first > second)
- return std::make_optional<TextRange>(second, first - second);
- if (first < second)
- return std::make_optional<TextRange>(first, second - first);
- return std::nullopt;
- }
-
- constexpr static std::pair<unsigned, unsigned> ToTwoSides(
- std::optional<TextRange> text_range, unsigned default_position = 0) {
- if (text_range.has_value())
- return std::make_pair(
- text_range.value().position,
- text_range.value().position + text_range.value().count);
- return std::make_pair(default_position, default_position);
- }
-
- constexpr TextRange() = default;
- constexpr TextRange(const unsigned position, const unsigned count)
- : position(position), count(count) {}
-
- unsigned position = 0;
- unsigned count = 0;
-};
-} // namespace cru::ui
diff --git a/src/ui/window_class.hpp b/src/ui/window_class.hpp
deleted file mode 100644
index 72a7c431..00000000
--- a/src/ui/window_class.hpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-#include "pre.hpp"
-
-#include <Windows.h>
-
-#include "base.hpp"
-
-namespace cru::ui {
-class WindowClass : public Object {
- public:
- WindowClass(const String& name, WNDPROC window_proc, HINSTANCE h_instance);
- WindowClass(const WindowClass& other) = delete;
- WindowClass(WindowClass&& other) = delete;
- WindowClass& operator=(const WindowClass& other) = delete;
- WindowClass& operator=(WindowClass&& other) = delete;
- ~WindowClass() override = default;
-
- const wchar_t* GetName() const { return name_.c_str(); }
-
- ATOM GetAtom() const { return atom_; }
-
- private:
- String name_;
- ATOM atom_;
-};
-} // namespace cru::ui
diff --git a/src/util/format.hpp b/src/util/format.hpp
deleted file mode 100644
index 7c1cee05..00000000
--- a/src/util/format.hpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#pragma once
-#include "pre.hpp"
-
-#include "base.hpp"
-
-namespace cru::util {
-namespace details {
-template <typename T>
-struct TypeTag {};
-
-constexpr StringView PlaceHolder(TypeTag<String>) { return StringView(L"{}"); }
-
-constexpr MultiByteStringView PlaceHolder(TypeTag<MultiByteString>) {
- return MultiByteStringView("{}");
-}
-
-template <typename TString>
-void FormatInternal(TString& string) {
- const auto find_result = string.find(PlaceHolder(TypeTag<TString>{}));
- if (find_result != TString::npos)
- throw std::invalid_argument("There is more placeholders than args.");
-}
-
-template <typename TString, typename T, typename... TRest>
-void FormatInternal(TString& string, const T& arg, const TRest&... args) {
- const auto find_result = string.find(PlaceHolder(TypeTag<TString>{}));
- if (find_result == TString::npos)
- throw std::invalid_argument("There is less placeholders than args.");
-
- string.replace(find_result, 2, FormatToString(arg, TypeTag<TString>{}));
- FormatInternal<TString>(string, args...);
-}
-} // namespace details
-
-template <typename... T>
-String Format(const StringView& format, const T&... args) {
- String result(format);
- details::FormatInternal<String>(result, args...);
- return result;
-}
-
-template <typename... T>
-MultiByteString Format(const MultiByteStringView& format, const T&... args) {
- MultiByteString result(format);
- details::FormatInternal<MultiByteString>(result, args...);
- return result;
-}
-
-#define CRU_FORMAT_NUMBER(type) \
- inline String FormatToString(const type number, details::TypeTag<String>) { \
- return std::to_wstring(number); \
- } \
- inline MultiByteString FormatToString(const type number, \
- details::TypeTag<MultiByteString>) { \
- return std::to_string(number); \
- }
-
-CRU_FORMAT_NUMBER(int)
-CRU_FORMAT_NUMBER(short)
-CRU_FORMAT_NUMBER(long)
-CRU_FORMAT_NUMBER(long long)
-CRU_FORMAT_NUMBER(unsigned int)
-CRU_FORMAT_NUMBER(unsigned short)
-CRU_FORMAT_NUMBER(unsigned long)
-CRU_FORMAT_NUMBER(unsigned long long)
-CRU_FORMAT_NUMBER(float)
-CRU_FORMAT_NUMBER(double)
-
-#undef CRU_FORMAT_NUMBER
-
-inline StringView FormatToString(const String& string,
- details::TypeTag<String>) {
- return string;
-}
-
-inline MultiByteString FormatToString(const MultiByteString& string,
- details::TypeTag<MultiByteString>) {
- return string;
-}
-
-inline StringView FormatToString(const StringView& string,
- details::TypeTag<String>) {
- return string;
-}
-
-inline MultiByteStringView FormatToString(const MultiByteStringView& string,
- details::TypeTag<MultiByteString>) {
- return string;
-}
-
-inline StringView FormatToString(const wchar_t* string,
- details::TypeTag<String>) {
- return StringView(string);
-}
-
-inline MultiByteStringView FormatToString(const char* string,
- details::TypeTag<MultiByteString>) {
- return MultiByteString(string);
-}
-} // namespace cru::util