aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-01-01 22:52:01 +0800
committercrupest <crupest@outlook.com>2020-01-01 22:52:01 +0800
commit36708e88596364e81dc9ba2fd3cbddbcaedeedc0 (patch)
tree0c7990b9e64c6ea1e9df7c01f3521c4fbf7ea2a0 /src
parentae6f797561cdfa438ebef1fbbf94d784d315e655 (diff)
downloadcru-36708e88596364e81dc9ba2fd3cbddbcaedeedc0.tar.gz
cru-36708e88596364e81dc9ba2fd3cbddbcaedeedc0.tar.bz2
cru-36708e88596364e81dc9ba2fd3cbddbcaedeedc0.zip
...
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/ui/click_detector.cpp122
-rw-r--r--src/ui/controls/button.cpp74
-rw-r--r--src/ui/render/render_object.cpp10
-rw-r--r--src/ui/render/window_render_object.cpp21
-rw-r--r--src/win/native/window.cpp13
6 files changed, 144 insertions, 97 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index a6497222..f84a954a 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -4,6 +4,7 @@ add_library(cru_base STATIC
)
target_sources(cru_base PUBLIC
${CRU_BASE_INCLUDE_DIR}/base.hpp
+ ${CRU_BASE_INCLUDE_DIR}/bitmask.hpp
${CRU_BASE_INCLUDE_DIR}/event.hpp
${CRU_BASE_INCLUDE_DIR}/format.hpp
${CRU_BASE_INCLUDE_DIR}/logger.hpp
diff --git a/src/ui/click_detector.cpp b/src/ui/click_detector.cpp
index 05d6dce1..b620201c 100644
--- a/src/ui/click_detector.cpp
+++ b/src/ui/click_detector.cpp
@@ -1,5 +1,7 @@
#include "cru/ui/click_detector.hpp"
+#include "cru/common/logger.hpp"
+
#include <cassert>
#include <optional>
@@ -10,33 +12,119 @@ ClickDetector::ClickDetector(Control* control) {
event_rovoker_guards_.push_back(
EventRevokerGuard(control->MouseEnterEvent()->Direct()->AddHandler(
- [this, control](event::MouseEventArgs& args) {
- if
+ [this](event::MouseEventArgs&) {
+ if (this->enable_) {
+ if (this->state_ == ClickState::PressInactive) {
+ if ((this->button_ & this->trigger_button_)) {
+ this->SetState(ClickState::Press);
+ }
+ } else {
+ this->SetState(ClickState::Hover);
+ }
+ }
+ })));
+ event_rovoker_guards_.push_back(
+ EventRevokerGuard(control->MouseLeaveEvent()->Direct()->AddHandler(
+ [this](event::MouseEventArgs&) {
+ if (this->enable_) {
+ if (this->state_ == ClickState::Press) {
+ if ((this->button_ & this->trigger_button_)) {
+ this->SetState(ClickState::PressInactive);
+ }
+ } else {
+ this->SetState(ClickState::None);
+ }
+ }
})));
event_rovoker_guards_.push_back(
EventRevokerGuard(control->MouseDownEvent()->Direct()->AddHandler(
- [this, control](event::MouseButtonEventArgs& args) {
- if (!control->CaptureMouse()) return; // capture failed
- const auto button = args.GetMouseButton();
- FromButton(button) = args.GetPoint(); // save mouse down point
- begin_event_.Raise(button);
+ [this](event::MouseButtonEventArgs& args) {
+ const auto button = args.GetButton();
+ if (this->enable_ && (button & this->trigger_button_) &&
+ this->state_ == ClickState::Hover) {
+ if (!this->control_->CaptureMouse()) {
+ log::Debug("Failed to capture mouse when begin click.");
+ return;
+ }
+ this->down_point_ = args.GetPoint();
+ this->button_ = button;
+ this->SetState(ClickState::Press);
+ }
})));
event_rovoker_guards_.push_back(
EventRevokerGuard(control->MouseUpEvent()->Direct()->AddHandler(
- [this, control](event::MouseButtonEventArgs& args) {
- if (!control->IsMouseCaptured()) return;
- const auto button = args.GetMouseButton();
- auto& down_point = FromButton(button);
- if (down_point.has_value()) {
- event_.Raise(ClickEventArgs(control, down_point.value(),
- args.GetPoint(), button));
- end_event_.Raise(button);
- down_point = std::nullopt;
+ [this](event::MouseButtonEventArgs& args) {
+ const auto button = args.GetButton();
+ if (this->enable_ && (button & this->trigger_button_) &&
+ button == button_) {
+ if (this->state_ == ClickState::Press) {
+ this->SetState(ClickState::Hover);
+ this->event_.Raise(ClickEventArgs{this->control_,
+ this->down_point_,
+ args.GetPoint(), button});
+ this->control_->ReleaseMouse();
+ } else if (this->state_ == ClickState::PressInactive) {
+ this->SetState(ClickState::None);
+ this->control_->ReleaseMouse();
+ }
}
- control->ReleaseMouse();
})));
+} // namespace cru::ui
+
+void ClickDetector::SetEnabled(bool enable) {
+ if (enable == enable_) {
+ return;
+ }
+
+ enable_ = enable;
+ if (enable) {
+ SetState(control_->IsMouseOver() ? ClickState::Hover : ClickState::None);
+ } else {
+ if (state_ == ClickState::Press || state_ == ClickState::PressInactive) {
+ SetState(ClickState::None);
+ control_->ReleaseMouse();
+ } else if (state_ == ClickState::Hover) {
+ SetState(ClickState::None);
+ }
+ }
+}
+
+void ClickDetector::SetTriggerButton(MouseButton trigger_button) {
+ if (trigger_button == trigger_button_) {
+ return;
+ }
+
+ trigger_button_ = trigger_button;
+ if ((state_ == ClickState::Press || state_ == ClickState::PressInactive) &&
+ !(button_ & trigger_button)) {
+ SetState(control_->IsMouseOver() ? ClickState::Hover : ClickState::None);
+ control_->ReleaseMouse();
+ }
+}
+
+void ClickDetector::SetState(ClickState state) {
+#ifdef CRU_DEBUG
+ auto to_string = [](ClickState state) -> std::string_view {
+ switch (state) {
+ case ClickState::None:
+ return "None";
+ case ClickState::Hover:
+ return "Hover";
+ case ClickState::Press:
+ return "Press";
+ case ClickState::PressInactive:
+ return "PressInvactive";
+ default:
+ UnreachableCode();
+ }
+ };
+ log::Debug("Click state changed, new state: {}.", to_string(state));
+#endif
+
+ state_ = state;
+ state_change_event_.Raise(state);
}
} // namespace cru::ui
diff --git a/src/ui/controls/button.cpp b/src/ui/controls/button.cpp
index 75651a1d..7dc5a5d7 100644
--- a/src/ui/controls/button.cpp
+++ b/src/ui/controls/button.cpp
@@ -35,37 +35,27 @@ Button::Button() : click_detector_(this) {
Set(render_object_.get(), style_.normal);
render_object_->SetBorderEnabled(true);
- MouseEnterEvent()->Direct()->AddHandler([this](event::MouseEventArgs& args) {
- CRU_UNUSED(args)
-
- if (click_detector_.GetPressingButton() & trigger_button_) {
- SetState(ButtonState::Press);
- } else {
- SetState(ButtonState::Hover);
- }
- });
-
- MouseLeaveEvent()->Direct()->AddHandler([this](event::MouseEventArgs& args) {
- CRU_UNUSED(args)
-
- if (click_detector_.GetPressingButton() & trigger_button_) {
- SetState(ButtonState::Normal);
- } else {
- SetState(ButtonState::PressCancel);
- }
- });
-
- click_detector_.ClickBeginEvent()->AddHandler([this](MouseButton button) {
- if (button & trigger_button_) {
- SetState(ButtonState::Press);
- }
- });
-
- click_detector_.ClickEndEvent()->AddHandler([this](MouseButton button) {
- if (button & trigger_button_) {
- SetState(ButtonState::Hover);
- }
- });
+ click_detector_.StateChangeEvent()->AddHandler(
+ [this](const ClickState& state) {
+ switch (state) {
+ case ClickState::None:
+ Set(render_object_.get(), style_.normal);
+ SetCursor(GetSystemCursor(SystemCursorType::Arrow));
+ break;
+ case ClickState::Hover:
+ Set(render_object_.get(), style_.hover);
+ SetCursor(GetSystemCursor(SystemCursorType::Hand));
+ break;
+ case ClickState::Press:
+ Set(render_object_.get(), style_.press);
+ SetCursor(GetSystemCursor(SystemCursorType::Hand));
+ break;
+ case ClickState::PressInactive:
+ Set(render_object_.get(), style_.press_cancel);
+ SetCursor(GetSystemCursor(SystemCursorType::Arrow));
+ break;
+ }
+ });
}
render::RenderObject* Button::GetRenderObject() const {
@@ -78,26 +68,4 @@ void Button::OnChildChanged(Control* old_child, Control* new_child) {
render_object_->AddChild(new_child->GetRenderObject(), 0);
}
-void Button::OnStateChange(ButtonState oldState, ButtonState newState) {
- CRU_UNUSED(oldState)
-
- switch (newState) {
- case ButtonState::Normal:
- Set(render_object_.get(), style_.normal);
- SetCursor(GetSystemCursor(SystemCursorType::Arrow));
- break;
- case ButtonState::Hover:
- Set(render_object_.get(), style_.hover);
- SetCursor(GetSystemCursor(SystemCursorType::Hand));
- break;
- case ButtonState::Press:
- Set(render_object_.get(), style_.press);
- SetCursor(GetSystemCursor(SystemCursorType::Hand));
- break;
- case ButtonState::PressCancel:
- Set(render_object_.get(), style_.press_cancel);
- SetCursor(GetSystemCursor(SystemCursorType::Arrow));
- break;
- }
-}
} // namespace cru::ui::controls
diff --git a/src/ui/render/render_object.cpp b/src/ui/render/render_object.cpp
index 7f6255f7..d220b1c1 100644
--- a/src/ui/render/render_object.cpp
+++ b/src/ui/render/render_object.cpp
@@ -18,6 +18,7 @@ void RenderObject::AddChild(RenderObject* render_object, const int position) {
children_.insert(children_.cbegin() + position, render_object);
render_object->SetParent(this);
+ render_object->SetRenderHostRecursive(GetRenderHost());
OnAddChild(render_object, position);
}
@@ -30,6 +31,7 @@ void RenderObject::RemoveChild(const int position) {
const auto removed_child = *i;
children_.erase(i);
removed_child->SetParent(nullptr);
+ removed_child->SetRenderHostRecursive(nullptr);
OnRemoveChild(removed_child, position);
}
@@ -140,4 +142,12 @@ void RenderObject::NotifyAfterLayoutRecursive(RenderObject* render_object) {
NotifyAfterLayoutRecursive(o);
}
}
+
+void RenderObject::SetRenderHostRecursive(IRenderHost* host) {
+ SetRenderHost(host);
+ for (const auto child : GetChildren()) {
+ child->SetRenderHostRecursive(host);
+ }
+}
+
} // namespace cru::ui::render
diff --git a/src/ui/render/window_render_object.cpp b/src/ui/render/window_render_object.cpp
index 12fc2ce1..1001be87 100644
--- a/src/ui/render/window_render_object.cpp
+++ b/src/ui/render/window_render_object.cpp
@@ -88,27 +88,6 @@ RenderObject* WindowRenderObject::HitTest(const Point& point) {
return Rect{Point{}, GetSize()}.IsPointInside(point) ? this : nullptr;
}
-namespace {
-void SetRenderHostRecursive(RenderObject* render_object, IRenderHost* host) {
- render_object->SetRenderHost(host);
- for (const auto child : render_object->GetChildren()) {
- SetRenderHostRecursive(child, host);
- }
-}
-} // namespace
-
-void WindowRenderObject::OnAddChild(RenderObject* new_child, int position) {
- CRU_UNUSED(position)
-
- SetRenderHostRecursive(new_child, render_host_.get());
-}
-
-void WindowRenderObject::OnRemoveChild(RenderObject* new_child, int position) {
- CRU_UNUSED(position)
-
- SetRenderHostRecursive(new_child, nullptr);
-}
-
Size WindowRenderObject::OnMeasureContent(const Size& available_size) {
if (const auto child = GetChild()) child->Measure(available_size);
return available_size;
diff --git a/src/win/native/window.cpp b/src/win/native/window.cpp
index d3c12a44..a8016676 100644
--- a/src/win/native/window.cpp
+++ b/src/win/native/window.cpp
@@ -155,6 +155,7 @@ bool WinNativeWindow::ReleaseMouse() {
void WinNativeWindow::RequestRepaint() {
if (IsValid()) {
+ log::Debug("A repaint is requested.");
if (!::InvalidateRect(hwnd_, nullptr, FALSE))
throw Win32Error(::GetLastError(), "Failed to invalidate window.");
if (!::UpdateWindow(hwnd_))
@@ -262,7 +263,7 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg,
POINT point;
point.x = GET_X_LPARAM(l_param);
point.y = GET_Y_LPARAM(l_param);
- OnMouseDownInternal(platform::native::MouseButton::Left, point);
+ OnMouseDownInternal(platform::native::mouse_buttons::left, point);
*result = 0;
return true;
}
@@ -270,7 +271,7 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg,
POINT point;
point.x = GET_X_LPARAM(l_param);
point.y = GET_Y_LPARAM(l_param);
- OnMouseUpInternal(platform::native::MouseButton::Left, point);
+ OnMouseUpInternal(platform::native::mouse_buttons::left, point);
*result = 0;
return true;
}
@@ -278,7 +279,7 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg,
POINT point;
point.x = GET_X_LPARAM(l_param);
point.y = GET_Y_LPARAM(l_param);
- OnMouseDownInternal(platform::native::MouseButton::Right, point);
+ OnMouseDownInternal(platform::native::mouse_buttons::right, point);
*result = 0;
return true;
}
@@ -286,7 +287,7 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg,
POINT point;
point.x = GET_X_LPARAM(l_param);
point.y = GET_Y_LPARAM(l_param);
- OnMouseUpInternal(platform::native::MouseButton::Right, point);
+ OnMouseUpInternal(platform::native::mouse_buttons::right, point);
*result = 0;
return true;
}
@@ -294,7 +295,7 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg,
POINT point;
point.x = GET_X_LPARAM(l_param);
point.y = GET_Y_LPARAM(l_param);
- OnMouseDownInternal(platform::native::MouseButton::Middle, point);
+ OnMouseDownInternal(platform::native::mouse_buttons::middle, point);
*result = 0;
return true;
}
@@ -302,7 +303,7 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg,
POINT point;
point.x = GET_X_LPARAM(l_param);
point.y = GET_Y_LPARAM(l_param);
- OnMouseUpInternal(platform::native::MouseButton::Middle, point);
+ OnMouseUpInternal(platform::native::mouse_buttons::middle, point);
*result = 0;
return true;
}