diff options
author | crupest <crupest@outlook.com> | 2018-11-09 20:57:29 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2018-11-09 20:57:29 +0800 |
commit | 9ef75fe91837394620edb91f332065a4f34a0281 (patch) | |
tree | 39a3e67f9a34ce44cc65b74d0ec82691cffd5dfa /src | |
parent | efdce672123284847bd7fb6f12ac1ec96f28f3ef (diff) | |
download | cru-9ef75fe91837394620edb91f332065a4f34a0281.tar.gz cru-9ef75fe91837394620edb91f332065a4f34a0281.tar.bz2 cru-9ef75fe91837394620edb91f332065a4f34a0281.zip |
Add singleton system.
Diffstat (limited to 'src')
-rw-r--r-- | src/application.cpp | 13 | ||||
-rw-r--r-- | src/application.hpp | 46 | ||||
-rw-r--r-- | src/base.hpp | 8 | ||||
-rw-r--r-- | src/graph/graph.cpp | 5 | ||||
-rw-r--r-- | src/graph/graph.hpp | 15 | ||||
-rw-r--r-- | src/timer.cpp | 15 | ||||
-rw-r--r-- | src/timer.hpp | 6 | ||||
-rw-r--r-- | src/ui/animations/animation.cpp | 10 | ||||
-rw-r--r-- | src/ui/animations/animation.hpp | 10 | ||||
-rw-r--r-- | src/ui/control.cpp | 1 | ||||
-rw-r--r-- | src/ui/controls/text_box.cpp | 1 | ||||
-rw-r--r-- | src/ui/layout_base.cpp | 6 | ||||
-rw-r--r-- | src/ui/layout_base.hpp | 4 | ||||
-rw-r--r-- | src/ui/window.cpp | 22 | ||||
-rw-r--r-- | src/ui/window.hpp | 3 |
15 files changed, 93 insertions, 72 deletions
diff --git a/src/application.cpp b/src/application.cpp index df99cab8..dce01b11 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -5,7 +5,6 @@ #include "ui/window.hpp" #include "ui/cursor.hpp" #include "graph/graph.hpp" -#include "ui/animations/animation.hpp" namespace cru { constexpr auto god_window_class_name = L"GodWindowClass"; @@ -64,12 +63,12 @@ namespace cru { case WM_TIMER: { const auto id = static_cast<UINT_PTR>(w_param); - const auto action = application_->GetTimerManager()->GetAction(id); + const auto action = TimerManager::GetInstance()->GetAction(id); if (action.has_value()) { (action.value().second)(); if (!action.value().first) - Application::GetInstance()->GetTimerManager()->KillTimer(id); + TimerManager::GetInstance()->KillTimer(id); return 0; } break; @@ -117,11 +116,6 @@ namespace cru { instance_ = this; - window_manager_ = std::make_unique<ui::WindowManager>(); - graph_manager_ = std::make_unique<graph::GraphManager>(); - timer_manager_ = std::make_unique<TimerManager>(); - animation_manager_ = std::make_unique<ui::animations::details::AnimationManager>(); - god_window_ = std::make_unique<GodWindow>(this); #ifdef CRU_DEBUG_LAYOUT @@ -137,7 +131,8 @@ namespace cru { Application::~Application() { - animation_manager_.reset(); + for (auto i = singleton_list_.crbegin(); i != singleton_list_.crend(); ++i) + delete *i; instance_ = nullptr; } diff --git a/src/application.hpp b/src/application.hpp index fe38ba0f..7357bbaf 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -4,6 +4,8 @@ #include <memory> #include <optional> #include <functional> +#include <typeindex> +#include <type_traits> #include "base.hpp" @@ -86,25 +88,6 @@ namespace cru int Run(); void Quit(int quit_code); - ui::WindowManager* GetWindowManager() const - { - return window_manager_.get(); - } - - graph::GraphManager* GetGraphManager() const - { - return graph_manager_.get(); - } - - TimerManager* GetTimerManager() const - { - return timer_manager_.get(); - } - - ui::animations::details::AnimationManager* GetAnimationManager() const - { - return animation_manager_.get(); - } HINSTANCE GetInstanceHandle() const { @@ -116,6 +99,23 @@ namespace cru return god_window_.get(); } + // Resolve a singleton. + // All singletons will be delete in reverse order of resolve. + template<typename T, typename = std::enable_if_t<std::is_base_of_v<Object, T>>> + T* ResolveSingleton(const std::function<T*(Application*)>& creator) + { + const auto& index = std::type_index{typeid(T)}; + const auto find_result = singleton_map_.find(index); + if (find_result != singleton_map_.cend()) + return static_cast<T*>(find_result->second); + + auto singleton = creator(this); + singleton_map_.emplace(index, static_cast<Object*>(singleton)); + singleton_list_.push_back(singleton); + return singleton; + } + + CaretInfo GetCaretInfo() const { return caret_info_; @@ -130,14 +130,12 @@ namespace cru private: HINSTANCE h_instance_; - - std::unique_ptr<ui::WindowManager> window_manager_; - std::unique_ptr<graph::GraphManager> graph_manager_; - std::unique_ptr<TimerManager> timer_manager_; - std::unique_ptr<ui::animations::details::AnimationManager> animation_manager_; std::unique_ptr<GodWindow> god_window_; + std::unordered_map<std::type_index, Object*> singleton_map_; + std::list<Object*> singleton_list_; // used for reverse destroy. + #ifdef CRU_DEBUG_LAYOUT DebugLayoutResource debug_layout_resource_; #endif diff --git a/src/base.hpp b/src/base.hpp index d4a3548f..5d8cb9ce 100644 --- a/src/base.hpp +++ b/src/base.hpp @@ -5,19 +5,15 @@ #include <string> -#include <type_traits> #include <stdexcept> -#include <memory> #include <string_view> #include <chrono> #include <optional> +// ReSharper disable once CppUnusedIncludeDirective +#include <type_traits> namespace cru { - template<typename T> struct is_shared_ptr : std::false_type {}; - template<typename T> struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {}; - template<typename T> constexpr bool is_shared_ptr_v = is_shared_ptr<T>::value; - template<typename T> struct type_tag {}; //typedefs diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index febb7fee..d37b5e2d 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -116,7 +116,10 @@ namespace cru::graph GraphManager* GraphManager::GetInstance() { - return Application::GetInstance()->GetGraphManager(); + return Application::GetInstance()->ResolveSingleton<GraphManager>([](auto) + { + return new GraphManager{}; + }); } GraphManager::GraphManager() diff --git a/src/graph/graph.hpp b/src/graph/graph.hpp index 9ef2e4b8..b98db5f4 100644 --- a/src/graph/graph.hpp +++ b/src/graph/graph.hpp @@ -2,9 +2,9 @@ #include "system_headers.hpp" #include <memory> +#include <functional> #include "base.hpp" -#include "application.hpp" namespace cru::graph @@ -62,13 +62,14 @@ namespace cru::graph float y; }; - class GraphManager : public Object + class GraphManager final : public Object { public: static GraphManager* GetInstance(); - public: + private: GraphManager(); + public: GraphManager(const GraphManager& other) = delete; GraphManager(GraphManager&& other) = delete; GraphManager& operator=(const GraphManager& other) = delete; @@ -135,12 +136,12 @@ namespace cru::graph inline int DipToPixelX(const float dip_x) { - return DipToPixelInternal(dip_x, Application::GetInstance()->GetGraphManager()->GetDpi().x); + return DipToPixelInternal(dip_x, GraphManager::GetInstance()->GetDpi().x); } inline int DipToPixelY(const float dip_y) { - return DipToPixelInternal(dip_y, Application::GetInstance()->GetGraphManager()->GetDpi().y); + return DipToPixelInternal(dip_y, GraphManager::GetInstance()->GetDpi().y); } inline float DipToPixelInternal(const int pixel, const float dpi) @@ -150,12 +151,12 @@ namespace cru::graph inline float PixelToDipX(const int pixel_x) { - return DipToPixelInternal(pixel_x, Application::GetInstance()->GetGraphManager()->GetDpi().x); + return DipToPixelInternal(pixel_x, GraphManager::GetInstance()->GetDpi().x); } inline float PixelToDipY(const int pixel_y) { - return DipToPixelInternal(pixel_y, Application::GetInstance()->GetGraphManager()->GetDpi().y); + return DipToPixelInternal(pixel_y, GraphManager::GetInstance()->GetDpi().y); } Microsoft::WRL::ComPtr<ID2D1DeviceContext> WindowRenderTarget::GetD2DDeviceContext() const diff --git a/src/timer.cpp b/src/timer.cpp index 3d89d567..c839a48d 100644 --- a/src/timer.cpp +++ b/src/timer.cpp @@ -4,9 +4,12 @@ namespace cru { - inline TimerManager* GetTimerManager() + TimerManager* TimerManager::GetInstance() { - return Application::GetInstance()->GetTimerManager(); + return Application::GetInstance()->ResolveSingleton<TimerManager>([](auto) + { + return new TimerManager{}; + }); } UINT_PTR TimerManager::CreateTimer(const UINT milliseconds, const bool loop, const TimerAction& action) @@ -41,20 +44,20 @@ namespace cru } - void TimerTask::Cancel() + void TimerTask::Cancel() const { - GetTimerManager()->KillTimer(id_); + TimerManager::GetInstance()->KillTimer(id_); } TimerTask SetTimeout(std::chrono::milliseconds milliseconds, const TimerAction& action) { - const auto id = GetTimerManager()->CreateTimer(static_cast<UINT>(milliseconds.count()), false, 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 = GetTimerManager()->CreateTimer(static_cast<UINT>(milliseconds.count()), true, action); + const auto id = TimerManager::GetInstance()->CreateTimer(static_cast<UINT>(milliseconds.count()), true, action); return TimerTask(id); } } diff --git a/src/timer.hpp b/src/timer.hpp index 5d6e8b71..3488db45 100644 --- a/src/timer.hpp +++ b/src/timer.hpp @@ -16,7 +16,11 @@ namespace cru 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; @@ -47,7 +51,7 @@ namespace cru TimerTask& operator=(TimerTask&& other) = default; ~TimerTask() = default; - void Cancel(); + void Cancel() const; private: UINT_PTR id_; diff --git a/src/ui/animations/animation.cpp b/src/ui/animations/animation.cpp index 33c743cf..b1f92a3e 100644 --- a/src/ui/animations/animation.cpp +++ b/src/ui/animations/animation.cpp @@ -2,6 +2,8 @@ #include <utility> +#include "application.hpp" + namespace cru::ui::animations { namespace details @@ -66,6 +68,14 @@ namespace cru::ui::animations AnimationTimeUnit current_time_ = AnimationTimeUnit::zero(); }; + AnimationManager* AnimationManager::GetInstance() + { + return Application::GetInstance()->ResolveSingleton<AnimationManager>([](auto) + { + return new AnimationManager{}; + }); + } + AnimationManager::AnimationManager() { diff --git a/src/ui/animations/animation.hpp b/src/ui/animations/animation.hpp index 99389f33..f25e4699 100644 --- a/src/ui/animations/animation.hpp +++ b/src/ui/animations/animation.hpp @@ -3,7 +3,6 @@ #include <unordered_map> #include "base.hpp" -#include "application.hpp" #include "timer.hpp" namespace cru::ui::animations @@ -53,13 +52,10 @@ namespace cru::ui::animations class AnimationManager : public Object { public: - static AnimationManager* GetInstance() - { - return Application::GetInstance()->GetAnimationManager(); - } - - public: + static AnimationManager* GetInstance(); + private: AnimationManager(); + public: AnimationManager(const AnimationManager& other) = delete; AnimationManager(AnimationManager&& other) = delete; AnimationManager& operator=(const AnimationManager& other) = delete; diff --git a/src/ui/control.cpp b/src/ui/control.cpp index bb3e35f8..31910328 100644 --- a/src/ui/control.cpp +++ b/src/ui/control.cpp @@ -3,6 +3,7 @@ #include <algorithm> #include "window.hpp" +#include "application.hpp" #include "graph/graph.hpp" #include "exception.hpp" #include "cru_debug.hpp" diff --git a/src/ui/controls/text_box.cpp b/src/ui/controls/text_box.cpp index 605e1a24..cb5d79a2 100644 --- a/src/ui/controls/text_box.cpp +++ b/src/ui/controls/text_box.cpp @@ -5,6 +5,7 @@ #include "graph/graph.hpp" #include "exception.hpp" +#include "application.hpp" namespace cru::ui::controls { diff --git a/src/ui/layout_base.cpp b/src/ui/layout_base.cpp index a384500a..5363c52b 100644 --- a/src/ui/layout_base.cpp +++ b/src/ui/layout_base.cpp @@ -8,8 +8,10 @@ namespace cru::ui { LayoutManager* LayoutManager::GetInstance() { - static LayoutManager layout_manager; - return &layout_manager; + return Application::GetInstance()->ResolveSingleton<LayoutManager>([](auto) + { + return new LayoutManager{}; + }); } void LayoutManager::InvalidateControlPositionCache(Control * control) diff --git a/src/ui/layout_base.hpp b/src/ui/layout_base.hpp index 1c35f0b7..512301b7 100644 --- a/src/ui/layout_base.hpp +++ b/src/ui/layout_base.hpp @@ -147,9 +147,9 @@ namespace cru::ui { public: static LayoutManager* GetInstance(); - - public: + private: LayoutManager() = default; + public: LayoutManager(const LayoutManager& other) = delete; LayoutManager(LayoutManager&& other) = delete; LayoutManager& operator=(const LayoutManager& other) = delete; diff --git a/src/ui/window.cpp b/src/ui/window.cpp index e426bc78..349b78ff 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -31,7 +31,7 @@ namespace cru::ui } LRESULT __stdcall GeneralWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { - auto window = Application::GetInstance()->GetWindowManager()->FromHandle(hWnd); + auto window = WindowManager::GetInstance()->FromHandle(hWnd); LRESULT result; if (window != nullptr && window->HandleWindowMessage(hWnd, Msg, wParam, lParam, result)) @@ -40,6 +40,14 @@ namespace cru::ui return DefWindowProc(hWnd, Msg, wParam, lParam); } + WindowManager* WindowManager::GetInstance() + { + return Application::GetInstance()->ResolveSingleton<WindowManager>([](auto) + { + return new WindowManager{}; + }); + } + WindowManager::WindowManager() { general_window_class_ = std::make_unique<WindowClass>( L"CruUIWindowClass", @@ -106,20 +114,20 @@ namespace cru::ui } Window::Window() : Control(WindowConstructorTag{}, this), control_list_({ this }) { - const auto app = Application::GetInstance(); + const auto window_manager = WindowManager::GetInstance(); hwnd_ = CreateWindowEx(0, - app->GetWindowManager()->GetGeneralWindowClass()->GetName(), + window_manager->GetGeneralWindowClass()->GetName(), L"", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - nullptr, nullptr, app->GetInstanceHandle(), nullptr + nullptr, nullptr, Application::GetInstance()->GetInstanceHandle(), nullptr ); if (hwnd_ == nullptr) throw std::runtime_error("Failed to create window."); - app->GetWindowManager()->RegisterWindow(hwnd_, this); + window_manager->RegisterWindow(hwnd_, this); - render_target_ = app->GetGraphManager()->CreateWindowRenderTarget(hwnd_); + render_target_ = graph::GraphManager::GetInstance()->CreateWindowRenderTarget(hwnd_); SetCursor(cursors::arrow); } @@ -511,7 +519,7 @@ namespace cru::ui } void Window::OnDestroyInternal() { - Application::GetInstance()->GetWindowManager()->UnregisterWindow(hwnd_); + WindowManager::GetInstance()->UnregisterWindow(hwnd_); hwnd_ = nullptr; } diff --git a/src/ui/window.hpp b/src/ui/window.hpp index 9f773f55..2609594d 100644 --- a/src/ui/window.hpp +++ b/src/ui/window.hpp @@ -44,7 +44,10 @@ namespace cru::ui class WindowManager : public Object { public: + static WindowManager* GetInstance(); + private: WindowManager(); + public: WindowManager(const WindowManager& other) = delete; WindowManager(WindowManager&& other) = delete; WindowManager& operator=(const WindowManager& other) = delete; |