aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2019-06-14 00:44:14 +0800
committercrupest <crupest@outlook.com>2019-06-14 00:44:14 +0800
commit5ec370e5f91ad8b5ed7717eb93f4e3240ea4e784 (patch)
tree970188397f236715d3d021ddcfcbdeeee73ee860
parent7b1e9fd2410c9d4fafbe5de9459b18775e6cc465 (diff)
downloadcru-5ec370e5f91ad8b5ed7717eb93f4e3240ea4e784.tar.gz
cru-5ec370e5f91ad8b5ed7717eb93f4e3240ea4e784.tar.bz2
cru-5ec370e5f91ad8b5ed7717eb93f4e3240ea4e784.zip
...
-rw-r--r--include/cru/common/base.hpp5
-rw-r--r--include/cru/common/event.hpp57
-rw-r--r--include/cru/platform/native/native_event.hpp12
-rw-r--r--include/cru/platform/native/native_window.hpp23
-rw-r--r--include/cru/ui/window.hpp21
-rw-r--r--include/cru/win/native/win_native_window.hpp36
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/ui/window.cpp84
-rw-r--r--src/win/native/win_native_window.cpp11
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) {}