aboutsummaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
author杨宇千 <crupest@outlook.com>2019-09-13 23:08:37 +0800
committer杨宇千 <crupest@outlook.com>2019-09-13 23:08:37 +0800
commite3423168a298139051e6bc8b9bacf8b7d594c94e (patch)
treeca76324602782efe342d57e6e030a6aafa774a13 /src/ui
parent1028f0206ca3ddb1c5a5ca5b0b25ffcabddacb16 (diff)
downloadcru-e3423168a298139051e6bc8b9bacf8b7d594c94e.tar.gz
cru-e3423168a298139051e6bc8b9bacf8b7d594c94e.tar.bz2
cru-e3423168a298139051e6bc8b9bacf8b7d594c94e.zip
...
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/routed_event_dispatch.hpp61
-rw-r--r--src/ui/window.cpp61
2 files changed, 101 insertions, 21 deletions
diff --git a/src/ui/routed_event_dispatch.hpp b/src/ui/routed_event_dispatch.hpp
index 83702005..b032c0a3 100644
--- a/src/ui/routed_event_dispatch.hpp
+++ b/src/ui/routed_event_dispatch.hpp
@@ -1,6 +1,8 @@
#pragma once
#include "cru/ui/control.hpp"
+#include "cru/common/logger.hpp"
+
#include <list>
namespace cru::ui {
@@ -18,9 +20,20 @@ namespace cru::ui {
// "original_sender", which is unchanged. And "args" will be perfectly forwarded
// as the rest arguments.
template <typename EventArgs, typename... Args>
-void DispatchEvent(Control* const original_sender,
+void DispatchEvent(const std::wstring_view& event_name,
+ Control* const original_sender,
event::RoutedEvent<EventArgs>* (Control::*event_ptr)(),
Control* const last_receiver, Args&&... args) {
+ if (original_sender == last_receiver) {
+#ifdef CRU_DEBUG
+ log::Debug(
+ L"Routed event {} no need to dispatch (original_sender == "
+ L"last_receiver). Original sender is {}.",
+ event_name, original_sender->GetControlType());
+#endif
+ return;
+ }
+
std::list<Control*> receive_list;
auto parent = original_sender;
@@ -29,15 +42,44 @@ void DispatchEvent(Control* const original_sender,
parent = parent->GetParent();
}
+#ifdef CRU_DEBUG
+ {
+ std::wstring log = L"Dispatch routed event ";
+ log += event_name;
+ log += L". Path (parent first): ";
+ auto i = receive_list.crbegin();
+ const auto end = --receive_list.crend();
+ for (; i != end; ++i) {
+ log += (*i)->GetControlType();
+ log += L" -> ";
+ }
+ log += (*i)->GetControlType();
+ log::Debug(log);
+ }
+#endif
+
auto handled = false;
+#ifdef CRU_DEBUG
+ int count = 0;
+#endif
+
// tunnel
for (auto i = receive_list.crbegin(); i != receive_list.crend(); ++i) {
+#ifdef CRU_DEBUG
+ count++;
+#endif
EventArgs event_args(*i, original_sender, std::forward<Args>(args)...);
static_cast<Event<EventArgs&>*>(((*i)->*event_ptr)()->Tunnel())
->Raise(event_args);
if (event_args.IsHandled()) {
handled = true;
+#ifdef CRU_DEBUG
+ log::Debug(
+ L"Routed event is short-circuit in TUNNEL at {}-st control (count "
+ L"from parent).",
+ count);
+#endif
break;
}
}
@@ -45,10 +87,21 @@ void DispatchEvent(Control* const original_sender,
// bubble
if (!handled) {
for (auto i : receive_list) {
+#ifdef CRU_DEBUG
+ count--;
+#endif
EventArgs event_args(i, original_sender, std::forward<Args>(args)...);
static_cast<Event<EventArgs&>*>((i->*event_ptr)()->Bubble())
->Raise(event_args);
- if (event_args.IsHandled()) break;
+ if (event_args.IsHandled()) {
+#ifdef CRU_DEBUG
+ log::Debug(
+ L"Routed event is short-circuit in BUBBLE at {}-st control (count "
+ L"from parent).",
+ count);
+#endif
+ break;
+ }
}
}
@@ -58,5 +111,9 @@ void DispatchEvent(Control* const original_sender,
static_cast<Event<EventArgs&>*>((i->*event_ptr)()->Direct())
->Raise(event_args);
}
+
+#ifdef CRU_DEBUG
+ log::Debug(L"Routed event dispatch finished.");
+#endif
}
} // namespace cru::ui
diff --git a/src/ui/window.cpp b/src/ui/window.cpp
index b599e479..834b924c 100644
--- a/src/ui/window.cpp
+++ b/src/ui/window.cpp
@@ -10,6 +10,22 @@
#include <list>
namespace cru::ui {
+namespace event_names {
+#define CRU_DEFINE_EVENT_NAME(name) constexpr const wchar_t* name = L#name;
+
+CRU_DEFINE_EVENT_NAME(LoseFocus)
+CRU_DEFINE_EVENT_NAME(GainFocus)
+CRU_DEFINE_EVENT_NAME(MouseEnter)
+CRU_DEFINE_EVENT_NAME(MouseLeave)
+CRU_DEFINE_EVENT_NAME(MouseMove)
+CRU_DEFINE_EVENT_NAME(MouseDown)
+CRU_DEFINE_EVENT_NAME(MouseUp)
+CRU_DEFINE_EVENT_NAME(KeyDown)
+CRU_DEFINE_EVENT_NAME(KeyUp)
+
+#undef CRU_DEFINE_EVENT_NAME
+} // namespace event_names
+
namespace {
bool IsAncestor(Control* control, Control* ancestor) {
while (control != nullptr) {
@@ -136,11 +152,13 @@ bool Window::RequestFocusFor(Control* control) {
if (focus_control_ == control) return true;
- DispatchEvent(focus_control_, &Control::LoseFocusEvent, nullptr, false);
+ DispatchEvent(event_names::LoseFocus, focus_control_,
+ &Control::LoseFocusEvent, nullptr, false);
focus_control_ = control;
- DispatchEvent(control, &Control::GainFocusEvent, nullptr, false);
+ DispatchEvent(event_names::GainFocus, control, &Control::GainFocusEvent,
+ nullptr, false);
return true;
}
@@ -198,14 +216,16 @@ void Window::OnNativeResize(const Size& size) {
}
void Window::OnNativeFocus(bool focus) {
- focus
- ? DispatchEvent(focus_control_, &Control::GainFocusEvent, nullptr, true)
- : DispatchEvent(focus_control_, &Control::LoseFocusEvent, nullptr, true);
+ focus ? DispatchEvent(event_names::GainFocus, focus_control_,
+ &Control::GainFocusEvent, nullptr, true)
+ : DispatchEvent(event_names::LoseFocus, focus_control_,
+ &Control::LoseFocusEvent, nullptr, true);
}
void Window::OnNativeMouseEnterLeave(bool enter) {
if (!enter) {
- DispatchEvent(mouse_hover_control_, &Control::MouseLeaveEvent, nullptr);
+ DispatchEvent(event_names::MouseLeave, mouse_hover_control_,
+ &Control::MouseLeaveEvent, nullptr);
mouse_hover_control_ = nullptr;
}
}
@@ -221,16 +241,16 @@ void Window::OnNativeMouseMove(const Point& point) {
mouse_captured_control_, new_control_mouse_hover, point, false, true);
DispatchMouseHoverControlChangeEvent(
old_control_mouse_hover, mouse_captured_control_, point, true, false);
- DispatchEvent(mouse_captured_control_, &Control::MouseMoveEvent, nullptr,
- point);
+ DispatchEvent(event_names::MouseMove, mouse_captured_control_,
+ &Control::MouseMoveEvent, nullptr, point);
UpdateCursor();
return;
}
DispatchMouseHoverControlChangeEvent(
old_control_mouse_hover, new_control_mouse_hover, point, false, false);
- DispatchEvent(new_control_mouse_hover, &Control::MouseMoveEvent, nullptr,
- point);
+ DispatchEvent(event_names::MouseMove, new_control_mouse_hover,
+ &Control::MouseMoveEvent, nullptr, point);
UpdateCursor();
}
@@ -238,24 +258,26 @@ void Window::OnNativeMouseDown(
const platform::native::NativeMouseButtonEventArgs& args) {
Control* control =
mouse_captured_control_ ? mouse_captured_control_ : HitTest(args.point);
- DispatchEvent(control, &Control::MouseDownEvent, nullptr, args.point,
- args.button);
+ DispatchEvent(event_names::MouseDown, control, &Control::MouseDownEvent,
+ nullptr, args.point, args.button);
}
void Window::OnNativeMouseUp(
const platform::native::NativeMouseButtonEventArgs& args) {
Control* control =
mouse_captured_control_ ? mouse_captured_control_ : HitTest(args.point);
- DispatchEvent(control, &Control::MouseUpEvent, nullptr, args.point,
- args.button);
+ DispatchEvent(event_names::MouseUp, control, &Control::MouseUpEvent, nullptr,
+ args.point, args.button);
}
void Window::OnNativeKeyDown(int virtual_code) {
- DispatchEvent(focus_control_, &Control::KeyDownEvent, nullptr, virtual_code);
+ DispatchEvent(event_names::KeyDown, focus_control_, &Control::KeyDownEvent,
+ nullptr, virtual_code);
}
void Window::OnNativeKeyUp(int virtual_code) {
- DispatchEvent(focus_control_, &Control::KeyUpEvent, nullptr, virtual_code);
+ DispatchEvent(event_names::KeyUp, focus_control_, &Control::KeyUpEvent,
+ nullptr, virtual_code);
}
void Window::DispatchMouseHoverControlChangeEvent(Control* old_control,
@@ -268,11 +290,12 @@ void Window::DispatchMouseHoverControlChangeEvent(Control* old_control,
const auto lowest_common_ancestor =
FindLowestCommonAncestor(old_control, new_control);
if (!no_leave && old_control != nullptr)
- DispatchEvent(old_control, &Control::MouseLeaveEvent,
+ DispatchEvent(event_names::MouseLeave, old_control,
+ &Control::MouseLeaveEvent,
lowest_common_ancestor); // dispatch mouse leave event.
if (!no_enter && new_control != nullptr) {
- DispatchEvent(new_control, &Control::MouseEnterEvent,
- lowest_common_ancestor,
+ DispatchEvent(event_names::MouseEnter, new_control,
+ &Control::MouseEnterEvent, lowest_common_ancestor,
point); // dispatch mouse enter event.
}
}