diff options
author | crupest <crupest@outlook.com> | 2020-01-01 22:52:01 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-01-01 22:52:01 +0800 |
commit | 36708e88596364e81dc9ba2fd3cbddbcaedeedc0 (patch) | |
tree | 0c7990b9e64c6ea1e9df7c01f3521c4fbf7ea2a0 /src/ui/click_detector.cpp | |
parent | ae6f797561cdfa438ebef1fbbf94d784d315e655 (diff) | |
download | cru-36708e88596364e81dc9ba2fd3cbddbcaedeedc0.tar.gz cru-36708e88596364e81dc9ba2fd3cbddbcaedeedc0.tar.bz2 cru-36708e88596364e81dc9ba2fd3cbddbcaedeedc0.zip |
...
Diffstat (limited to 'src/ui/click_detector.cpp')
-rw-r--r-- | src/ui/click_detector.cpp | 122 |
1 files changed, 105 insertions, 17 deletions
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 |