aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2019-04-19 23:20:09 +0800
committercrupest <crupest@outlook.com>2019-04-19 23:20:09 +0800
commitea87825d58ab5b58dd360c3f080518c07a865db0 (patch)
tree4b497ef3687d682368e0fde4b86293565583a63a
parent7351020a582d70a1495249fba87d342c8a1fb634 (diff)
downloadcru-ea87825d58ab5b58dd360c3f080518c07a865db0.tar.gz
cru-ea87825d58ab5b58dd360c3f080518c07a865db0.tar.bz2
cru-ea87825d58ab5b58dd360c3f080518c07a865db0.zip
...
-rw-r--r--include/cru/common/event.hpp5
-rw-r--r--include/cru/platform/native/ui_applicaition.hpp2
-rw-r--r--include/cru/win/graph/d2d_painter.hpp (renamed from include/cru/win/graph/win_painter.hpp)20
-rw-r--r--include/cru/win/native/win_application.hpp6
-rw-r--r--src/ui/ui_manager.cpp8
-rw-r--r--src/win/graph/CMakeLists.txt2
-rw-r--r--src/win/graph/d2d_painter.cpp (renamed from src/win/graph/win_painter.cpp)32
-rw-r--r--src/win/graph/graph_manager.cpp6
-rw-r--r--src/win/graph/win_font.cpp2
-rw-r--r--src/win/native/win_application.cpp33
-rw-r--r--src/win/native/win_native_window.cpp1
-rw-r--r--src/win/native/window_manager.cpp5
-rw-r--r--src/win/native/window_manager.hpp2
-rw-r--r--src/win/native/window_painter.cpp13
-rw-r--r--src/win/native/window_painter.hpp6
15 files changed, 89 insertions, 54 deletions
diff --git a/include/cru/common/event.hpp b/include/cru/common/event.hpp
index 987bcdd6..741dcd99 100644
--- a/include/cru/common/event.hpp
+++ b/include/cru/common/event.hpp
@@ -102,8 +102,9 @@ class Event : public details::EventBase {
template <typename... Args>
void Raise(Args&&... args) {
- for (const auto& handler : handlers_)
- (handler.second)(std::forward<Args>(args)...);
+ std::list<EventHandler> handlers;
+ for (const auto& [key, handler] : handlers_) handlers.push_back(handler);
+ for (const auto& handler : handlers) handler(std::forward<Args>(args)...);
}
protected:
diff --git a/include/cru/platform/native/ui_applicaition.hpp b/include/cru/platform/native/ui_applicaition.hpp
index 8d42d813..17ff703d 100644
--- a/include/cru/platform/native/ui_applicaition.hpp
+++ b/include/cru/platform/native/ui_applicaition.hpp
@@ -18,6 +18,8 @@ struct UiApplication : public virtual Interface {
virtual int Run() = 0;
virtual void Quit(int quite_code) = 0;
+ virtual void AddOnQuitHandler(const std::function<void()>& handler) = 0;
+
virtual void InvokeLater(const std::function<void()>& action) = 0;
virtual unsigned long SetTimeout(std::chrono::milliseconds milliseconds,
const std::function<void()>& action) = 0;
diff --git a/include/cru/win/graph/win_painter.hpp b/include/cru/win/graph/d2d_painter.hpp
index 8351cb7b..d33dced4 100644
--- a/include/cru/win/graph/win_painter.hpp
+++ b/include/cru/win/graph/d2d_painter.hpp
@@ -6,14 +6,14 @@
namespace cru::win::graph {
class GraphManager;
-class WinPainter : public Object, public virtual platform::graph::Painter {
+class D2DPainter : public Object, public virtual platform::graph::Painter {
public:
- explicit WinPainter(ID2D1RenderTarget* render_target);
- WinPainter(const WinPainter& other) = delete;
- WinPainter(WinPainter&& other) = delete;
- WinPainter& operator=(const WinPainter& other) = delete;
- WinPainter& operator=(WinPainter&& other) = delete;
- ~WinPainter() override;
+ explicit D2DPainter(ID2D1RenderTarget* render_target);
+ D2DPainter(const D2DPainter& other) = delete;
+ D2DPainter(D2DPainter&& other) = delete;
+ D2DPainter& operator=(const D2DPainter& other) = delete;
+ D2DPainter& operator=(D2DPainter&& other) = delete;
+ ~D2DPainter() override = default;
platform::Matrix GetTransform() override;
void SetTransform(const platform::Matrix& matrix) override;
@@ -29,8 +29,8 @@ class WinPainter : public Object, public virtual platform::graph::Painter {
void DrawText(const ui::Point& offset,
platform::graph::TextLayout* text_layout,
platform::graph::Brush* brush) override;
- void EndDraw() override;
- bool IsDisposed() override { return is_disposed_; }
+ void EndDraw() override final;
+ bool IsDisposed() override final { return is_disposed_; }
void EndDrawAndDeleteThis() {
EndDraw();
@@ -38,7 +38,7 @@ class WinPainter : public Object, public virtual platform::graph::Painter {
}
protected:
- virtual void DoEndDraw();
+ virtual void DoEndDraw() = 0;
private:
ID2D1RenderTarget* render_target_;
diff --git a/include/cru/win/native/win_application.hpp b/include/cru/win/native/win_application.hpp
index 458b10ae..5bdb753e 100644
--- a/include/cru/win/native/win_application.hpp
+++ b/include/cru/win/native/win_application.hpp
@@ -16,7 +16,7 @@ class WinApplication : public Object,
static WinApplication* GetInstance();
private:
- static WinApplication* instance_;
+ static WinApplication* instance;
private:
explicit WinApplication(HINSTANCE h_instance);
@@ -32,6 +32,8 @@ class WinApplication : public Object,
int Run() override;
void Quit(int quit_code) override;
+ void AddOnQuitHandler(const std::function<void()>& handler) override;
+
void InvokeLater(const std::function<void()>& action) override;
unsigned long SetTimeout(std::chrono::milliseconds milliseconds,
const std::function<void()>& action) override;
@@ -55,5 +57,7 @@ class WinApplication : public Object,
std::shared_ptr<GodWindow> god_window_;
std::shared_ptr<TimerManager> timer_manager_;
std::shared_ptr<WindowManager> window_manager_;
+
+ std::vector<std::function<void()>> quit_handlers_;
};
} // namespace cru::win::native
diff --git a/src/ui/ui_manager.cpp b/src/ui/ui_manager.cpp
index 2ac1c8e7..0c3a8f49 100644
--- a/src/ui/ui_manager.cpp
+++ b/src/ui/ui_manager.cpp
@@ -19,8 +19,12 @@ PredefineResources::PredefineResources() {
}
UiManager* UiManager::GetInstance() {
- static UiManager instance;
- return &instance;
+ static UiManager* instance = new UiManager();
+ platform::native::UiApplication::GetInstance()->AddOnQuitHandler([] {
+ delete instance;
+ instance = nullptr;
+ });
+ return instance;
}
UiManager::UiManager() : predefine_resources_(new PredefineResources()) {}
diff --git a/src/win/graph/CMakeLists.txt b/src/win/graph/CMakeLists.txt
index 7781e09a..61749a6a 100644
--- a/src/win/graph/CMakeLists.txt
+++ b/src/win/graph/CMakeLists.txt
@@ -1,9 +1,9 @@
add_library(cru_win_graph STATIC
+ d2d_painter.cpp
graph_manager.cpp
win_brush.cpp
win_font.cpp
win_geometry.cpp
win_graph_factory.cpp
- win_painter.cpp
win_text_layout.cpp)
target_link_libraries(cru_win_graph PUBLIC D3D11 D2d1 DWrite cru_win_base)
diff --git a/src/win/graph/win_painter.cpp b/src/win/graph/d2d_painter.cpp
index 69ce1141..26f6bef0 100644
--- a/src/win/graph/win_painter.cpp
+++ b/src/win/graph/d2d_painter.cpp
@@ -1,4 +1,4 @@
-#include "cru/win/graph/win_painter.hpp"
+#include "cru/win/graph/d2d_painter.hpp"
#include "cru/win/exception.hpp"
#include "cru/win/graph/d2d_util.hpp"
@@ -10,31 +10,29 @@
#include <cassert>
namespace cru::win::graph {
-WinPainter::WinPainter(ID2D1RenderTarget* render_target) {
+D2DPainter::D2DPainter(ID2D1RenderTarget* render_target) {
assert(render_target);
render_target_ = render_target;
}
-WinPainter::~WinPainter() { EndDraw(); }
-
-platform::Matrix WinPainter::GetTransform() {
+platform::Matrix D2DPainter::GetTransform() {
assert(!IsDisposed());
D2D1_MATRIX_3X2_F m;
render_target_->GetTransform(&m);
return util::Convert(m);
}
-void WinPainter::SetTransform(const platform::Matrix& matrix) {
+void D2DPainter::SetTransform(const platform::Matrix& matrix) {
assert(!IsDisposed());
render_target_->SetTransform(util::Convert(matrix));
}
-void WinPainter::Clear(const ui::Color& color) {
+void D2DPainter::Clear(const ui::Color& color) {
assert(!IsDisposed());
render_target_->Clear(util::Convert(color));
}
-void WinPainter::StrokeRectangle(const ui::Rect& rectangle,
+void D2DPainter::StrokeRectangle(const ui::Rect& rectangle,
platform::graph::Brush* brush, float width) {
assert(!IsDisposed());
const auto b = dynamic_cast<WinBrush*>(brush);
@@ -43,7 +41,7 @@ void WinPainter::StrokeRectangle(const ui::Rect& rectangle,
width);
}
-void WinPainter::FillRectangle(const ui::Rect& rectangle,
+void D2DPainter::FillRectangle(const ui::Rect& rectangle,
platform::graph::Brush* brush) {
assert(!IsDisposed());
const auto b = dynamic_cast<WinBrush*>(brush);
@@ -51,7 +49,7 @@ void WinPainter::FillRectangle(const ui::Rect& rectangle,
render_target_->FillRectangle(util::Convert(rectangle), b->GetD2DBrush());
}
-void WinPainter::StrokeGeometry(platform::graph::Geometry* geometry,
+void D2DPainter::StrokeGeometry(platform::graph::Geometry* geometry,
platform::graph::Brush* brush, float width) {
assert(!IsDisposed());
const auto g = dynamic_cast<WinGeometry*>(geometry);
@@ -62,7 +60,7 @@ void WinPainter::StrokeGeometry(platform::graph::Geometry* geometry,
render_target_->DrawGeometry(g->GetNative(), b->GetD2DBrush(), width);
}
-void WinPainter::FillGeometry(platform::graph::Geometry* geometry,
+void D2DPainter::FillGeometry(platform::graph::Geometry* geometry,
platform::graph::Brush* brush) {
assert(!IsDisposed());
const auto g = dynamic_cast<WinGeometry*>(geometry);
@@ -73,7 +71,7 @@ void WinPainter::FillGeometry(platform::graph::Geometry* geometry,
render_target_->FillGeometry(g->GetNative(), b->GetD2DBrush());
}
-void WinPainter::DrawText(const ui::Point& offset,
+void D2DPainter::DrawText(const ui::Point& offset,
platform::graph::TextLayout* text_layout,
platform::graph::Brush* brush) {
assert(!IsDisposed());
@@ -86,14 +84,10 @@ void WinPainter::DrawText(const ui::Point& offset,
t->GetDWriteTextLayout(), b->GetD2DBrush());
}
-void WinPainter::EndDraw() {
- if (!IsDisposed()) {
+void D2DPainter::EndDraw() {
+ if (!is_disposed_) {
+ is_disposed_ = true;
DoEndDraw();
}
}
-
-void WinPainter::DoEndDraw() {
- ThrowIfFailed(render_target_->EndDraw());
- is_disposed_ = true;
-}
} // namespace cru::win::graph
diff --git a/src/win/graph/graph_manager.cpp b/src/win/graph/graph_manager.cpp
index a4306b1b..30e1a14e 100644
--- a/src/win/graph/graph_manager.cpp
+++ b/src/win/graph/graph_manager.cpp
@@ -2,10 +2,12 @@
#include "cru/win/exception.hpp"
+#include <cassert>
+
namespace cru::win::graph {
GraphManager* GraphManager::GetInstance() {
- static GraphManager instance;
- return &instance;
+ static GraphManager* instance = new GraphManager();
+ return instance;
}
GraphManager::GraphManager() {
diff --git a/src/win/graph/win_font.cpp b/src/win/graph/win_font.cpp
index 0eb5e6b2..96983d3e 100644
--- a/src/win/graph/win_font.cpp
+++ b/src/win/graph/win_font.cpp
@@ -13,7 +13,7 @@ WinFontDescriptor::WinFontDescriptor(GraphManager* graph_manager,
float font_size) {
assert(graph_manager);
std::array<wchar_t, LOCALE_NAME_MAX_LENGTH> buffer;
- if (!::GetUserDefaultLocaleName(buffer.data(), buffer.size()))
+ if (!::GetUserDefaultLocaleName(buffer.data(), static_cast<int>(buffer.size())))
throw Win32Error(::GetLastError(), "Failed to get locale.");
ThrowIfFailed(graph_manager->GetDWriteFactory()->CreateTextFormat(
diff --git a/src/win/native/win_application.cpp b/src/win/native/win_application.cpp
index 72e12fa0..6c39453f 100644
--- a/src/win/native/win_application.cpp
+++ b/src/win/native/win_application.cpp
@@ -1,6 +1,7 @@
#include "cru/win/native/win_application.hpp"
#include "cru/win/exception.hpp"
+#include "cru/win/graph/graph_manager.hpp"
#include "cru/win/native/god_window.hpp"
#include "cru/win/native/win_native_window.hpp"
#include "god_window_message.hpp"
@@ -17,19 +18,22 @@ UiApplication* UiApplication::GetInstance() {
} // namespace cru::platform::native
namespace cru::win::native {
-WinApplication* WinApplication::instance_ = nullptr;
+WinApplication* WinApplication::instance = nullptr;
+
+namespace {
+bool application_constructing = false;
+}
WinApplication* WinApplication::GetInstance() {
- if (instance_ == nullptr)
- instance_ = new WinApplication(::GetModuleHandleW(nullptr));
- return instance_;
+ if (instance == nullptr && !application_constructing) {
+ application_constructing = true;
+ 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;
+ assert(instance == nullptr);
if (!::IsWindows8OrGreater())
throw std::runtime_error("Must run on Windows 8 or later.");
@@ -39,7 +43,8 @@ WinApplication::WinApplication(HINSTANCE h_instance) : h_instance_(h_instance) {
window_manager_ = std::make_shared<WindowManager>(this);
}
-WinApplication::~WinApplication() { instance_ = nullptr; }
+WinApplication::~WinApplication() {
+ instance = nullptr; }
int WinApplication::Run() {
MSG msg;
@@ -47,11 +52,21 @@ int WinApplication::Run() {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
+
+ for (const auto& handler : quit_handlers_) handler();
+
+ delete graph::GraphManager::GetInstance();
+ delete this;
+
return static_cast<int>(msg.wParam);
}
void WinApplication::Quit(const int quit_code) { ::PostQuitMessage(quit_code); }
+void WinApplication::AddOnQuitHandler(const std::function<void()>& handler) {
+ quit_handlers_.push_back(handler);
+}
+
void WinApplication::InvokeLater(const std::function<void()>& action) {
// copy the action to a safe place
auto p_action_copy = new std::function<void()>(action);
diff --git a/src/win/native/win_native_window.cpp b/src/win/native/win_native_window.cpp
index 0afad4e6..1d3b15ba 100644
--- a/src/win/native/win_native_window.cpp
+++ b/src/win/native/win_native_window.cpp
@@ -254,6 +254,7 @@ RECT WinNativeWindow::GetClientRectPixel() {
void WinNativeWindow::OnDestroyInternal() {
application_->GetWindowManager()->UnregisterWindow(hwnd_);
hwnd_ = nullptr;
+ destroy_event_.Raise();
if (delete_this_on_destroy_)
application_->InvokeLater([this] { delete this; });
}
diff --git a/src/win/native/window_manager.cpp b/src/win/native/window_manager.cpp
index a2fcdb54..5fea5a27 100644
--- a/src/win/native/window_manager.cpp
+++ b/src/win/native/window_manager.cpp
@@ -26,6 +26,11 @@ WindowManager::WindowManager(WinApplication* application) {
L"CruUIWindowClass", GeneralWndProc, application->GetInstanceHandle());
}
+WindowManager::~WindowManager() {
+ for (const auto [key, window] : window_map_)
+ delete window;
+}
+
void WindowManager::RegisterWindow(HWND hwnd, WinNativeWindow* window) {
assert(window_map_.count(hwnd) == 0); // The hwnd is already in the map.
window_map_.emplace(hwnd, window);
diff --git a/src/win/native/window_manager.hpp b/src/win/native/window_manager.hpp
index fa5bbe9d..8fab9cfc 100644
--- a/src/win/native/window_manager.hpp
+++ b/src/win/native/window_manager.hpp
@@ -19,7 +19,7 @@ class WindowManager : public Object {
WindowManager(WindowManager&& other) = delete;
WindowManager& operator=(const WindowManager& other) = delete;
WindowManager& operator=(WindowManager&& other) = delete;
- ~WindowManager() override = default;
+ ~WindowManager() override;
// Get the general window class for creating ordinary window.
std::shared_ptr<WindowClass> GetGeneralWindowClass() const {
diff --git a/src/win/native/window_painter.cpp b/src/win/native/window_painter.cpp
index 46364cdd..4e98a7fd 100644
--- a/src/win/native/window_painter.cpp
+++ b/src/win/native/window_painter.cpp
@@ -1,5 +1,6 @@
#include "window_painter.hpp"
+#include "cru/win/exception.hpp"
#include "cru/win/graph/graph_manager.hpp"
#include "cru/win/native/window_render_target.hpp"
@@ -7,7 +8,7 @@
namespace cru::win::native {
WindowPainter::WindowPainter(WinNativeWindow* window)
- : WinPainter(window->GetWindowRenderTarget()
+ : D2DPainter(window->GetWindowRenderTarget()
->GetGraphManager()
->GetD2D1DeviceContext()),
window_(window) {
@@ -18,7 +19,13 @@ WindowPainter::WindowPainter(WinNativeWindow* window)
->BeginDraw();
}
+WindowPainter::~WindowPainter() { EndDraw(); }
+
void WindowPainter::DoEndDraw() {
- WinPainter::DoEndDraw();
- window_->GetWindowRenderTarget()->Present(); }
+ ThrowIfFailed(window_->GetWindowRenderTarget()
+ ->GetGraphManager()
+ ->GetD2D1DeviceContext()
+ ->EndDraw());
+ window_->GetWindowRenderTarget()->Present();
+}
} // namespace cru::win::native
diff --git a/src/win/native/window_painter.hpp b/src/win/native/window_painter.hpp
index 0e6ab2cb..78c0717c 100644
--- a/src/win/native/window_painter.hpp
+++ b/src/win/native/window_painter.hpp
@@ -1,16 +1,16 @@
#pragma once
-#include "cru/win/graph/win_painter.hpp"
+#include "cru/win/graph/d2d_painter.hpp"
#include "cru/win/native/win_native_window.hpp"
namespace cru::win::native {
-class WindowPainter : public graph::WinPainter {
+class WindowPainter : public graph::D2DPainter {
public:
explicit WindowPainter(WinNativeWindow* window);
WindowPainter(const WindowPainter& other) = delete;
WindowPainter& operator=(const WindowPainter& other) = delete;
WindowPainter(WindowPainter&& other) = delete;
WindowPainter& operator=(WindowPainter&& other) = delete;
- ~WindowPainter() override = default;
+ ~WindowPainter() override;
protected:
void DoEndDraw() override;