From 9e2d63adb90c293f4bc2893b0de7655aea2ecc85 Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 26 May 2019 23:38:34 +0800 Subject: ... --- include/cru/platform/graph/graph_factory.hpp | 6 +++- include/cru/platform/native/native_window.hpp | 4 +-- include/cru/platform/native/ui_applicaition.hpp | 24 +++++++++---- include/cru/ui/window.hpp | 6 ++-- include/cru/win/graph/win_graph_factory.hpp | 2 +- include/cru/win/native/win_application.hpp | 17 +++++---- include/cru/win/native/win_native_window.hpp | 4 +-- src/main.cpp | 4 +-- src/ui/ui_manager.cpp | 2 +- src/ui/window.cpp | 2 +- src/win/native/win_application.cpp | 47 +++++++++++++------------ 11 files changed, 69 insertions(+), 49 deletions(-) diff --git a/include/cru/platform/graph/graph_factory.hpp b/include/cru/platform/graph/graph_factory.hpp index b2619e8d..60d4ed8a 100644 --- a/include/cru/platform/graph/graph_factory.hpp +++ b/include/cru/platform/graph/graph_factory.hpp @@ -15,10 +15,14 @@ namespace cru::platform::graph { // Entry point of the graph module. +// If you create a IUiApplication instance, then you should not create +// IGraphFactory manually. IUiApplication will call +// IGraphFactory::CreateInstance and set auto-delete to true. +// The manual creation method of IGraphFactory provides a you a way to use graph +// related tools without interact with actual ui like window system. struct IGraphFactory : virtual Interface, virtual IAutoDelete { // Create a platform-specific instance and save it as the global instance. // Do not create the instance twice. Implements should assert for that. - // After the // After creating, get the instance by GetInstance. static IGraphFactory* CreateInstance(); diff --git a/include/cru/platform/native/native_window.hpp b/include/cru/platform/native/native_window.hpp index 0e076348..3a0fd3e1 100644 --- a/include/cru/platform/native/native_window.hpp +++ b/include/cru/platform/native/native_window.hpp @@ -10,7 +10,7 @@ struct IPainter; } namespace cru::platform::native { -struct NativeWindow : public virtual Interface { +struct INativeWindow : public virtual Interface { // Return if the window is still valid, that is, hasn't been closed or // destroyed. virtual bool IsValid() = 0; @@ -18,7 +18,7 @@ struct NativeWindow : public virtual Interface { virtual void Close() = 0; - virtual NativeWindow* GetParent() = 0; + virtual INativeWindow* GetParent() = 0; virtual bool IsVisible() = 0; virtual void SetVisible(bool is_visible) = 0; diff --git a/include/cru/platform/native/ui_applicaition.hpp b/include/cru/platform/native/ui_applicaition.hpp index 0188393e..655b8ea0 100644 --- a/include/cru/platform/native/ui_applicaition.hpp +++ b/include/cru/platform/native/ui_applicaition.hpp @@ -1,16 +1,28 @@ #pragma once #include "cru/common/base.hpp" +#include "cru/common/auto_delete.hpp" + #include #include #include namespace cru::platform::native { -struct NativeWindow; +struct INativeWindow; + +// The entry point of a ui application. +// It will call IGraphFactory::CreateInstance during its creation +// and set graph factory to be auto deleted. If you want to keep +// the graph factory then you should manually set it to false after +// creating the ui application. +struct IUiApplication : virtual Interface, virtual IAutoDelete { + // Create a platform-specific instance and save it as the global instance. + // Do not create the instance twice. Implements should assert for that. + // After creating, get the instance by GetInstance. + static IUiApplication* CreateInstance(); -struct UiApplication : public virtual Interface { - static UiApplication* CreateInstance(); - static UiApplication* GetInstance(); + // Get the global instance. If it is not created, then return nullptr. + static IUiApplication* GetInstance(); virtual int Run() = 0; virtual void Quit(int quite_code) = 0; @@ -24,7 +36,7 @@ struct UiApplication : public virtual Interface { const std::function& action) = 0; virtual void CancelTimer(unsigned long id) = 0; - virtual std::vector GetAllWindow() = 0; - virtual NativeWindow* CreateWindow(NativeWindow* parent) = 0; + virtual std::vector GetAllWindow() = 0; + virtual INativeWindow* CreateWindow(INativeWindow* parent) = 0; }; } // namespace cru::platform::ui diff --git a/include/cru/ui/window.hpp b/include/cru/ui/window.hpp index 140ac531..2ed05192 100644 --- a/include/cru/ui/window.hpp +++ b/include/cru/ui/window.hpp @@ -7,7 +7,7 @@ #include namespace cru::platform::native { -struct NativeWindow; +struct INativeWindow; } namespace cru::ui { @@ -39,7 +39,7 @@ class Window final : public ContentControl { render::RenderObject* GetRenderObject() const override; - platform::native::NativeWindow* GetNativeWindow() const { return native_window_; } + platform::native::INativeWindow* GetNativeWindow() const { return native_window_; } Control* GetMouseHoverControl() const { return mouse_hover_control_; } @@ -82,7 +82,7 @@ class Window final : public ContentControl { const Point& point); private: - platform::native::NativeWindow* native_window_; + platform::native::INativeWindow* native_window_; std::vector event_revoker_guards_; std::shared_ptr render_object_; diff --git a/include/cru/win/graph/win_graph_factory.hpp b/include/cru/win/graph/win_graph_factory.hpp index 02f1a0fc..2df7ed9a 100644 --- a/include/cru/win/graph/win_graph_factory.hpp +++ b/include/cru/win/graph/win_graph_factory.hpp @@ -8,7 +8,7 @@ namespace cru::win::graph { class WinGraphFactory : public Object, public virtual platform::graph::IGraphFactory, public virtual IWinNativeFactory { - friend IGraphFactory* ::cru::platform::graph::IGraphFactory::CreateInstance(); + friend IGraphFactory* IGraphFactory::CreateInstance(); public: static WinGraphFactory* GetInstance(); diff --git a/include/cru/win/native/win_application.hpp b/include/cru/win/native/win_application.hpp index 5bdb753e..d3e705e1 100644 --- a/include/cru/win/native/win_application.hpp +++ b/include/cru/win/native/win_application.hpp @@ -11,13 +11,11 @@ class TimerManager; class WindowManager; class WinApplication : public Object, - public virtual platform::native::UiApplication { + public virtual platform::native::IUiApplication { + friend IUiApplication* IUiApplication::CreateInstance(); public: static WinApplication* GetInstance(); - private: - static WinApplication* instance; - private: explicit WinApplication(HINSTANCE h_instance); @@ -41,9 +39,12 @@ class WinApplication : public Object, const std::function& action) override; void CancelTimer(unsigned long id) override; - std::vector GetAllWindow() override; - platform::native::NativeWindow* CreateWindow( - platform::native::NativeWindow* parent) override; + std::vector GetAllWindow() override; + platform::native::INativeWindow* CreateWindow( + platform::native::INativeWindow* parent) override; + + bool IsAutoDelete() const override { return auto_delete_; } + void SetAutoDelete(bool value) override { auto_delete_ = value; } HINSTANCE GetInstanceHandle() const { return h_instance_; } @@ -52,6 +53,8 @@ class WinApplication : public Object, WindowManager* GetWindowManager() const { return window_manager_.get(); } private: + bool auto_delete_ = false; + HINSTANCE h_instance_; std::shared_ptr god_window_; diff --git a/include/cru/win/native/win_native_window.hpp b/include/cru/win/native/win_native_window.hpp index 272ca14b..0fafc7fd 100644 --- a/include/cru/win/native/win_native_window.hpp +++ b/include/cru/win/native/win_native_window.hpp @@ -13,7 +13,7 @@ class WindowManager; class WindowRenderTarget; class WinNativeWindow : public Object, - public virtual platform::native::NativeWindow { + public virtual platform::native::INativeWindow { public: WinNativeWindow(WinApplication* application, std::shared_ptr window_class, DWORD window_style, @@ -29,7 +29,7 @@ class WinNativeWindow : public Object, void Close() override; - NativeWindow* GetParent() override { return parent_window_; } + INativeWindow* GetParent() override { return parent_window_; } bool IsVisible() override; void SetVisible(bool is_visible) override; diff --git a/src/main.cpp b/src/main.cpp index ecaebda5..ee381430 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,7 +5,7 @@ #include "cru/ui/controls/text_block.hpp" #include "cru/ui/window.hpp" -using cru::platform::native::UiApplication; +using cru::platform::native::IUiApplication; using cru::ui::Rect; using cru::ui::Thickness; using cru::ui::Window; @@ -21,7 +21,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, */ int main() { - auto application = UiApplication::GetInstance(); + std::unique_ptr application(IUiApplication::CreateInstance()); const auto window = Window::CreateOverlapped(); diff --git a/src/ui/ui_manager.cpp b/src/ui/ui_manager.cpp index 82b859c8..cc741ec5 100644 --- a/src/ui/ui_manager.cpp +++ b/src/ui/ui_manager.cpp @@ -20,7 +20,7 @@ PredefineResources::PredefineResources() { UiManager* UiManager::GetInstance() { static UiManager* instance = new UiManager(); - platform::native::UiApplication::GetInstance()->AddOnQuitHandler([] { + platform::native::IUiApplication::GetInstance()->AddOnQuitHandler([] { delete instance; instance = nullptr; }); diff --git a/src/ui/window.cpp b/src/ui/window.cpp index 1c035081..48f046f1 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -102,7 +102,7 @@ Window::Window(tag_overlapped_constructor) { using namespace std::placeholders; native_window_ = - platform::native::UiApplication::GetInstance()->CreateWindow(nullptr); + platform::native::IUiApplication::GetInstance()->CreateWindow(nullptr); render_object_.reset(new render::WindowRenderObject(this)); event_revoker_guards_.push_back( diff --git a/src/win/native/win_application.cpp b/src/win/native/win_application.cpp index 00a16ff1..586af331 100644 --- a/src/win/native/win_application.cpp +++ b/src/win/native/win_application.cpp @@ -11,26 +11,27 @@ #include #include -namespace cru::platform::native { -UiApplication* UiApplication::GetInstance() { - return win::native::WinApplication::GetInstance(); -} -} // namespace cru::platform::native - namespace cru::win::native { -WinApplication* WinApplication::instance = nullptr; - namespace { -bool application_constructing = false; +WinApplication* instance = nullptr; } +} // namespace cru::win::native -WinApplication* WinApplication::GetInstance() { - if (instance == nullptr && !application_constructing) { - application_constructing = true; - instance = new WinApplication(::GetModuleHandleW(nullptr)); - } - return instance; +namespace cru::platform::native { +IUiApplication* IUiApplication::CreateInstance() { + auto& i = ::cru::win::native::instance; // avoid long namespace prefix + assert(i == nullptr); + i = new win::native::WinApplication(::GetModuleHandleW(nullptr)); + return i; +} + +IUiApplication* IUiApplication::GetInstance() { + return ::cru::win::native::instance; } +} // namespace cru::platform::native + +namespace cru::win::native { +WinApplication* WinApplication::GetInstance() { return instance; } WinApplication::WinApplication(HINSTANCE h_instance) : h_instance_(h_instance) { assert(instance == nullptr); @@ -38,7 +39,8 @@ WinApplication::WinApplication(HINSTANCE h_instance) : h_instance_(h_instance) { if (!::IsWindows8OrGreater()) throw std::runtime_error("Must run on Windows 8 or later."); - graph::WinGraphFactory::CreateInstance(); + const auto graph_factory = platform::graph::IGraphFactory::CreateInstance(); + graph_factory->SetAutoDelete(true); god_window_ = std::make_shared(this); timer_manager_ = std::make_shared(god_window_.get()); @@ -56,8 +58,7 @@ int WinApplication::Run() { for (const auto& handler : quit_handlers_) handler(); - delete graph::WinGraphFactory::GetInstance(); - delete this; + if (auto_delete_) delete this; return static_cast(msg.wParam); } @@ -94,17 +95,17 @@ void WinApplication::CancelTimer(unsigned long id) { timer_manager_->KillTimer(static_cast(id)); } -std::vector WinApplication::GetAllWindow() { +std::vector WinApplication::GetAllWindow() { const auto&& windows = window_manager_->GetAllWindows(); - std::vector result; + std::vector result; for (const auto w : windows) { - result.push_back(static_cast(w)); + result.push_back(static_cast(w)); } return result; } -platform::native::NativeWindow* WinApplication::CreateWindow( - platform::native::NativeWindow* parent) { +platform::native::INativeWindow* WinApplication::CreateWindow( + platform::native::INativeWindow* parent) { WinNativeWindow* p = nullptr; if (parent != nullptr) { p = dynamic_cast(parent); -- cgit v1.2.3