diff options
author | crupest <crupest@outlook.com> | 2019-06-14 00:44:14 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2019-06-14 00:44:14 +0800 |
commit | 5ec370e5f91ad8b5ed7717eb93f4e3240ea4e784 (patch) | |
tree | 970188397f236715d3d021ddcfcbdeeee73ee860 | |
parent | 7b1e9fd2410c9d4fafbe5de9459b18775e6cc465 (diff) | |
download | cru-5ec370e5f91ad8b5ed7717eb93f4e3240ea4e784.tar.gz cru-5ec370e5f91ad8b5ed7717eb93f4e3240ea4e784.tar.bz2 cru-5ec370e5f91ad8b5ed7717eb93f4e3240ea4e784.zip |
...
-rw-r--r-- | include/cru/common/base.hpp | 5 | ||||
-rw-r--r-- | include/cru/common/event.hpp | 57 | ||||
-rw-r--r-- | include/cru/platform/native/native_event.hpp | 12 | ||||
-rw-r--r-- | include/cru/platform/native/native_window.hpp | 23 | ||||
-rw-r--r-- | include/cru/ui/window.hpp | 21 | ||||
-rw-r--r-- | include/cru/win/native/win_native_window.hpp | 36 | ||||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/ui/window.cpp | 84 | ||||
-rw-r--r-- | src/win/native/win_native_window.cpp | 11 |
9 files changed, 146 insertions, 104 deletions
diff --git a/include/cru/common/base.hpp b/include/cru/common/base.hpp index 7dfe8240..d72b97f2 100644 --- a/include/cru/common/base.hpp +++ b/include/cru/common/base.hpp @@ -13,6 +13,11 @@ class Object { }; struct Interface { + Interface() = default; + Interface(const Interface& other) = delete; + Interface(Interface&& other) = delete; + Interface& operator=(const Interface& other) = delete; + Interface& operator=(Interface&& other) = delete; virtual ~Interface() = default; }; } // namespace cru diff --git a/include/cru/common/event.hpp b/include/cru/common/event.hpp index d8a24330..af282c30 100644 --- a/include/cru/common/event.hpp +++ b/include/cru/common/event.hpp @@ -79,13 +79,44 @@ inline EventRevoker details::EventBase::CreateRevoker(EventHandlerToken token) { return EventRevoker(resolver_, token); } +template <typename TRaw> +using DeducedEventArgs = std::conditional_t< + std::is_lvalue_reference_v<TRaw>, TRaw, + std::conditional_t<std::is_scalar_v<TRaw>, TRaw, const TRaw&>>; + +// Provides an interface of event. +// +// Note that this class does not inherit Interface because Interface is +// public destructable, but I want to make this class not public +// destructable to prevent user from destructing it. +// +// IEvent only allow to add handler but not to raise the event. You may +// want to create an Event object and expose IEvent only so users won't +// be able to emit the event. +template <typename TEventArgs> +struct IEvent { + public: + using EventArgs = DeducedEventArgs<TEventArgs>; + using EventHandler = std::function<void(EventArgs)>; + + protected: + IEvent() = default; + IEvent(const IEvent& other) = delete; + IEvent(IEvent&& other) = delete; + IEvent& operator=(const IEvent& other) = delete; + IEvent& operator=(IEvent&& other) = delete; + ~IEvent() = default; + + public: + virtual EventRevoker AddHandler(const EventHandler& handler) = 0; + virtual EventRevoker AddHandler(EventHandler&& handler) = 0; +}; + // A non-copyable non-movable Event class. // It stores a list of event handlers. -template <typename... TArgs> -class Event : public details::EventBase { +template <typename TEventArgs> +class Event : public details::EventBase, public IEvent<TEventArgs> { public: - using EventHandler = std::function<void(TArgs...)>; - Event() = default; Event(const Event&) = delete; Event& operator=(const Event&) = delete; @@ -93,36 +124,26 @@ class Event : public details::EventBase { Event& operator=(Event&&) = delete; ~Event() = default; - EventRevoker AddHandler(const EventHandler& handler) { + EventRevoker AddHandler(const EventHandler& handler) override { const auto token = current_token_++; handlers_.emplace(token, handler); return CreateRevoker(token); } - EventRevoker AddHandler(EventHandler&& handler) { + EventRevoker AddHandler(EventHandler&& handler) override { const auto token = current_token_++; handlers_.emplace(token, std::move(handler)); return CreateRevoker(token); } - template <typename FArg> - EventRevoker AddHandler(FArg&& handler) { - static_assert(std::is_invocable_v<FArg, TArgs...>, - "Handler not invocable."); - const auto token = current_token_++; - handlers_.emplace(token, EventHandler(std::forward<FArg>(handler))); - return CreateRevoker(token); - } - - template <typename... FArg> - void Raise(FArg&&... args) { + void Raise(EventArgs args) { // copy the handlers to a list, because the handler might be removed // during executing, and the handler with its data will be destroyed. // if the handler is a lambda with member data, then the member data // will be destroyed and result in seg fault. std::list<EventHandler> handlers; for (const auto& [key, handler] : handlers_) handlers.push_back(handler); - for (const auto& handler : handlers) handler(std::forward<FArg>(args)...); + for (const auto& handler : handlers) handler(args); } protected: diff --git a/include/cru/platform/native/native_event.hpp b/include/cru/platform/native/native_event.hpp new file mode 100644 index 00000000..21db5f90 --- /dev/null +++ b/include/cru/platform/native/native_event.hpp @@ -0,0 +1,12 @@ +#pragma once +#include "cru/common/base.hpp" + +#include "basic_types.hpp" +#include "cru/common/ui_base.hpp" + +namespace cru::platform::native { +struct NativeMouseButtonEventArgs { + MouseButton button; + ui::Point point; +}; +} // namespace cru::platform::native diff --git a/include/cru/platform/native/native_window.hpp b/include/cru/platform/native/native_window.hpp index 3a0fd3e1..3e83a531 100644 --- a/include/cru/platform/native/native_window.hpp +++ b/include/cru/platform/native/native_window.hpp @@ -4,6 +4,7 @@ #include "basic_types.hpp" #include "cru/common/event.hpp" #include "cru/common/ui_base.hpp" +#include "native_event.hpp" namespace cru::platform::graph { struct IPainter; @@ -36,15 +37,15 @@ struct INativeWindow : public virtual Interface { virtual graph::IPainter* BeginPaint() = 0; - virtual Event<>* DestroyEvent() = 0; - virtual Event<const ui::Size&>* ResizeEvent() = 0; - virtual Event<>* PaintEvent() = 0; - virtual Event<bool>* FocusEvent() = 0; - virtual Event<bool>* MouseEnterLeaveEvent() = 0; - virtual Event<const ui::Point&>* MouseMoveEvent() = 0; - virtual Event<MouseButton, const ui::Point&>* MouseDownEvent() = 0; - virtual Event<MouseButton, const ui::Point&>* MouseUpEvent() = 0; - virtual Event<int>* KeyDownEvent() = 0; - virtual Event<int>* KeyUpEvent() = 0; + virtual IEvent<std::nullptr_t>* DestroyEvent() = 0; + virtual IEvent<std::nullptr_t>* PaintEvent() = 0; + virtual IEvent<ui::Size>* ResizeEvent() = 0; + virtual IEvent<bool>* FocusEvent() = 0; + virtual IEvent<bool>* MouseEnterLeaveEvent() = 0; + virtual IEvent<ui::Point>* MouseMoveEvent() = 0; + virtual IEvent<NativeMouseButtonEventArgs>* MouseDownEvent() = 0; + virtual IEvent<NativeMouseButtonEventArgs>* MouseUpEvent() = 0; + virtual IEvent<int>* KeyDownEvent() = 0; + virtual IEvent<int>* KeyUpEvent() = 0; }; -} // namespace cru::platform::ui +} // namespace cru::platform::native diff --git a/include/cru/ui/window.hpp b/include/cru/ui/window.hpp index 2ed05192..4bc0e41d 100644 --- a/include/cru/ui/window.hpp +++ b/include/cru/ui/window.hpp @@ -1,6 +1,7 @@ #pragma once #include "content_control.hpp" +#include "cru/platform/native/native_event.hpp" #include "event/ui_event.hpp" #include <memory> @@ -39,7 +40,9 @@ class Window final : public ContentControl { render::RenderObject* GetRenderObject() const override; - platform::native::INativeWindow* GetNativeWindow() const { return native_window_; } + platform::native::INativeWindow* GetNativeWindow() const { + return native_window_; + } Control* GetMouseHoverControl() const { return mouse_hover_control_; } @@ -59,18 +62,18 @@ class Window final : public ContentControl { //*************** region: native messages *************** - void OnNativeDestroy(); - void OnNativePaint(); + void OnNativeDestroy(std::nullptr_t); + void OnNativePaint(std::nullptr_t); void OnNativeResize(const Size& size); void OnNativeFocus(bool focus); void OnNativeMouseEnterLeave(bool enter); void OnNativeMouseMove(const Point& point); - void OnNativeMouseDown(platform::native::MouseButton button, - const Point& point); - void OnNativeMouseUp(platform::native::MouseButton button, - const Point& point); + void OnNativeMouseDown( + const platform::native::NativeMouseButtonEventArgs& args); + void OnNativeMouseUp( + const platform::native::NativeMouseButtonEventArgs& args); void OnNativeKeyDown(int virtual_code); void OnNativeKeyUp(int virtual_code); @@ -87,8 +90,8 @@ class Window final : public ContentControl { std::shared_ptr<render::WindowRenderObject> render_object_; - Control* mouse_hover_control_ = nullptr; + Control* mouse_hover_control_; - Control* focus_control_ = this; // "focus_control_" can't be nullptr + Control* focus_control_; // "focus_control_" can't be nullptr }; } // namespace cru::ui diff --git a/include/cru/win/native/win_native_window.hpp b/include/cru/win/native/win_native_window.hpp index 0fafc7fd..18de4f5d 100644 --- a/include/cru/win/native/win_native_window.hpp +++ b/include/cru/win/native/win_native_window.hpp @@ -47,28 +47,26 @@ class WinNativeWindow : public Object, platform::graph::IPainter* BeginPaint() override; - Event<>* DestroyEvent() override { return &destroy_event_; } - Event<const ui::Size&>* ResizeEvent() override { return &resize_event_; } - Event<>* PaintEvent() override { return &paint_event_; } - Event<bool>* FocusEvent() override { return &focus_event_; } - Event<bool>* MouseEnterLeaveEvent() override { + IEvent<std::nullptr_t>* DestroyEvent() override { return &destroy_event_; } + IEvent<std::nullptr_t>* PaintEvent() override { return &paint_event_; } + IEvent<ui::Size>* ResizeEvent() override { return &resize_event_; } + IEvent<bool>* FocusEvent() override { return &focus_event_; } + IEvent<bool>* MouseEnterLeaveEvent() override { return &mouse_enter_leave_event_; } - Event<const ui::Point&>* MouseMoveEvent() override { - return &mouse_move_event_; - } - Event<platform::native::MouseButton, const ui::Point&>* MouseDownEvent() + IEvent<ui::Point>* MouseMoveEvent() override { return &mouse_move_event_; } + IEvent<platform::native::NativeMouseButtonEventArgs>* MouseDownEvent() override { return &mouse_down_event_; } - Event<platform::native::MouseButton, const ui::Point&>* MouseUpEvent() + IEvent<platform::native::NativeMouseButtonEventArgs>* MouseUpEvent() override { return &mouse_up_event_; } - Event<int>* KeyDownEvent() override { return &key_down_event_; } - Event<int>* KeyUpEvent() override { return &key_up_event_; } + IEvent<int>* KeyDownEvent() override { return &key_down_event_; } + IEvent<int>* KeyUpEvent() override { return &key_up_event_; } - Event<WindowNativeMessageEventArgs&>* NativeMessageEvent() { + IEvent<WindowNativeMessageEventArgs&>* NativeMessageEvent() { return &native_message_event_; } @@ -121,14 +119,14 @@ class WinNativeWindow : public Object, std::shared_ptr<WindowRenderTarget> window_render_target_; - Event<> destroy_event_; - Event<const ui::Size&> resize_event_; - Event<> paint_event_; + Event<std::nullptr_t> destroy_event_; + Event<std::nullptr_t> paint_event_; + Event<ui::Size> resize_event_; Event<bool> focus_event_; Event<bool> mouse_enter_leave_event_; - Event<const ui::Point&> mouse_move_event_; - Event<platform::native::MouseButton, const ui::Point&> mouse_down_event_; - Event<platform::native::MouseButton, const ui::Point&> mouse_up_event_; + Event<ui::Point> mouse_move_event_; + Event<platform::native::NativeMouseButtonEventArgs> mouse_down_event_; + Event<platform::native::NativeMouseButtonEventArgs> mouse_up_event_; Event<int> key_down_event_; Event<int> key_up_event_; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fc5dd99e..e7f0edbb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -38,6 +38,7 @@ set(CRU_PLATFORM_NATIVE_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/platform/native) add_library(cru_platform_native INTERFACE) target_sources(cru_platform_native INTERFACE ${CRU_PLATFORM_NATIVE_INCLUDE_DIR}/basic_types.hpp + ${CRU_PLATFORM_NATIVE_INCLUDE_DIR}/native_event.hpp ${CRU_PLATFORM_NATIVE_INCLUDE_DIR}/native_window.hpp ${CRU_PLATFORM_NATIVE_INCLUDE_DIR}/ui_application.hpp ) diff --git a/src/ui/window.cpp b/src/ui/window.cpp index 48f046f1..2215826a 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -98,43 +98,42 @@ Window* Window::CreateOverlapped() { return new Window(tag_overlapped_constructor{}); } -Window::Window(tag_overlapped_constructor) { - using namespace std::placeholders; +namespace { +template <typename T> +void BindNativeEvent(Window* window, IEvent<T>* event, + void (Window::*handler)(typename IEvent<T>::EventArgs), + std::vector<EventRevokerGuard>& guard_pool) { + guard_pool.push_back(EventRevokerGuard( + event->AddHandler(std::bind(handler, window, std::placeholders::_1)))); +} +} // namespace +Window::Window(tag_overlapped_constructor) + : mouse_hover_control_(nullptr), focus_control_(this) { native_window_ = platform::native::IUiApplication::GetInstance()->CreateWindow(nullptr); render_object_.reset(new render::WindowRenderObject(this)); - event_revoker_guards_.push_back( - EventRevokerGuard(native_window_->DestroyEvent()->AddHandler( - std::bind(&Window::OnNativeDestroy, this)))); - event_revoker_guards_.push_back( - EventRevokerGuard(native_window_->PaintEvent()->AddHandler( - std::bind(&Window::OnNativePaint, this)))); - event_revoker_guards_.push_back( - EventRevokerGuard(native_window_->ResizeEvent()->AddHandler( - std::bind(&Window::OnNativeResize, this, _1)))); - event_revoker_guards_.push_back( - EventRevokerGuard(native_window_->FocusEvent()->AddHandler( - std::bind(&Window::OnNativeFocus, this, _1)))); - event_revoker_guards_.push_back( - EventRevokerGuard(native_window_->MouseEnterLeaveEvent()->AddHandler( - std::bind(&Window::OnNativeMouseEnterLeave, this, _1)))); - event_revoker_guards_.push_back( - EventRevokerGuard(native_window_->MouseMoveEvent()->AddHandler( - std::bind(&Window::OnNativeMouseMove, this, _1)))); - event_revoker_guards_.push_back( - EventRevokerGuard(native_window_->MouseDownEvent()->AddHandler( - std::bind(&Window::OnNativeMouseDown, this, _1, _2)))); - event_revoker_guards_.push_back( - EventRevokerGuard(native_window_->MouseUpEvent()->AddHandler( - std::bind(&Window::OnNativeMouseUp, this, _1, _2)))); - event_revoker_guards_.push_back( - EventRevokerGuard(native_window_->KeyDownEvent()->AddHandler( - std::bind(&Window::OnNativeKeyDown, this, _1)))); - event_revoker_guards_.push_back( - EventRevokerGuard(native_window_->KeyUpEvent()->AddHandler( - std::bind(&Window::OnNativeKeyUp, this, _1)))); + BindNativeEvent(this, native_window_->DestroyEvent(), + &Window::OnNativeDestroy, event_revoker_guards_); + BindNativeEvent(this, native_window_->PaintEvent(), &Window::OnNativePaint, + event_revoker_guards_); + BindNativeEvent(this, native_window_->ResizeEvent(), &Window::OnNativeResize, + event_revoker_guards_); + BindNativeEvent(this, native_window_->FocusEvent(), &Window::OnNativeFocus, + event_revoker_guards_); + BindNativeEvent(this, native_window_->MouseEnterLeaveEvent(), + &Window::OnNativeMouseEnterLeave, event_revoker_guards_); + BindNativeEvent(this, native_window_->MouseMoveEvent(), + &Window::OnNativeMouseMove, event_revoker_guards_); + BindNativeEvent(this, native_window_->MouseDownEvent(), + &Window::OnNativeMouseDown, event_revoker_guards_); + BindNativeEvent(this, native_window_->MouseUpEvent(), + &Window::OnNativeMouseUp, event_revoker_guards_); + BindNativeEvent(this, native_window_->KeyDownEvent(), + &Window::OnNativeKeyDown, event_revoker_guards_); + BindNativeEvent(this, native_window_->KeyUpEvent(), &Window::OnNativeKeyUp, + event_revoker_guards_); } Window::~Window() { @@ -174,9 +173,9 @@ Control* Window::HitTest(const Point& point) { return render_object_->HitTest(point)->GetAttachedControl(); } -void Window::OnNativeDestroy() { delete this; } +void Window::OnNativeDestroy(std::nullptr_t) { delete this; } -void Window::OnNativePaint() { +void Window::OnNativePaint(std::nullptr_t) { const auto painter = std::unique_ptr<platform::graph::IPainter>(native_window_->BeginPaint()); render_object_->Draw(painter.get()); @@ -212,15 +211,18 @@ void Window::OnNativeMouseMove(const Point& point) { point); } -void Window::OnNativeMouseDown(platform::native::MouseButton button, - const Point& point) { - Control* control = HitTest(point); - DispatchEvent(control, &Control::MouseDownEvent, nullptr, point, button); +void Window::OnNativeMouseDown( + const platform::native::NativeMouseButtonEventArgs& args) { + Control* control = HitTest(args.point); + DispatchEvent(control, &Control::MouseDownEvent, nullptr, args.point, + args.button); } -void Window::OnNativeMouseUp(platform::native::MouseButton button, const Point& point) { - Control* control = HitTest(point); - DispatchEvent(control, &Control::MouseUpEvent, nullptr, point, button); +void Window::OnNativeMouseUp( + const platform::native::NativeMouseButtonEventArgs& args) { + Control* control = HitTest(args.point); + DispatchEvent(control, &Control::MouseUpEvent, nullptr, args.point, + args.button); } void Window::OnNativeKeyDown(int virtual_code) { diff --git a/src/win/native/win_native_window.cpp b/src/win/native/win_native_window.cpp index a2f23a2c..9ca37321 100644 --- a/src/win/native/win_native_window.cpp +++ b/src/win/native/win_native_window.cpp @@ -254,13 +254,13 @@ RECT WinNativeWindow::GetClientRectPixel() { void WinNativeWindow::OnDestroyInternal() { application_->GetWindowManager()->UnregisterWindow(hwnd_); hwnd_ = nullptr; - destroy_event_.Raise(); + destroy_event_.Raise(nullptr); if (delete_this_on_destroy_) application_->InvokeLater([this] { delete this; }); } void WinNativeWindow::OnPaintInternal() { - paint_event_.Raise(); + paint_event_.Raise(nullptr); ValidateRect(hwnd_, nullptr); } @@ -302,8 +302,7 @@ void WinNativeWindow::OnMouseMoveInternal(const POINT point) { mouse_enter_leave_event_.Raise(true); } - const auto dip_point = PiToDip(point); - mouse_move_event_.Raise(dip_point); + mouse_move_event_.Raise(PiToDip(point)); } void WinNativeWindow::OnMouseLeaveInternal() { @@ -314,13 +313,13 @@ void WinNativeWindow::OnMouseLeaveInternal() { void WinNativeWindow::OnMouseDownInternal(platform::native::MouseButton button, POINT point) { const auto dip_point = PiToDip(point); - mouse_down_event_.Raise(button, dip_point); + mouse_down_event_.Raise({button, dip_point}); } void WinNativeWindow::OnMouseUpInternal(platform::native::MouseButton button, POINT point) { const auto dip_point = PiToDip(point); - mouse_up_event_.Raise(button, dip_point); + mouse_up_event_.Raise({button, dip_point}); } void WinNativeWindow::OnMouseWheelInternal(short delta, POINT point) {} |