diff options
author | crupest <crupest@outlook.com> | 2020-03-04 21:49:05 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-03-04 21:49:05 +0800 |
commit | abf604f8c6ec89c8d7df7062fe10fd17c60d5719 (patch) | |
tree | 82347efc2bef1966c0f1562d4467b7c389366ef9 /src/ui | |
parent | 79ba10135987cffc31496e8515c5372146d9b31d (diff) | |
download | cru-abf604f8c6ec89c8d7df7062fe10fd17c60d5719.tar.gz cru-abf604f8c6ec89c8d7df7062fe10fd17c60d5719.tar.bz2 cru-abf604f8c6ec89c8d7df7062fe10fd17c60d5719.zip |
...
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/controls/text_block.cpp | 1 | ||||
-rw-r--r-- | src/ui/controls/text_common.cpp | 168 |
2 files changed, 111 insertions, 58 deletions
diff --git a/src/ui/controls/text_block.cpp b/src/ui/controls/text_block.cpp index be064ea0..ece599e8 100644 --- a/src/ui/controls/text_block.cpp +++ b/src/ui/controls/text_block.cpp @@ -30,6 +30,7 @@ TextBlock::TextBlock() caret_brush_ = theme_resources->caret_brush; service_ = std::make_unique<TextControlService>(this, this); + service_->SetEnabled(true); } TextBlock::~TextBlock() = default; diff --git a/src/ui/controls/text_common.cpp b/src/ui/controls/text_common.cpp index d6bcdd03..fdfdcc2c 100644 --- a/src/ui/controls/text_common.cpp +++ b/src/ui/controls/text_common.cpp @@ -18,67 +18,39 @@ constexpr long long caret_blink_duration = 500; TextControlService::TextControlService(Control* control, ITextControl* text_control) - : control_(control), text_control_(text_control) { - event_revoker_guards_.push_back( - EventRevokerGuard{control->MouseDownEvent()->Direct()->AddHandler( - [this](event::MouseButtonEventArgs& args) { - if (this->select_down_button_.has_value()) { - return; - } else { - if (!this->control_->CaptureMouse()) return; - const auto text_render_object = - this->text_control_->GetTextRenderObject(); - this->select_down_button_ = args.GetButton(); - const auto result = text_render_object->TextHitTest( - text_render_object->FromRootToContent(args.GetPoint())); - const auto position = result.position + (result.trailing ? 1 : 0); - this->select_start_position_ = position; - log::Debug("Begin to select text. Position: {}", position); - } - })}); - - event_revoker_guards_.push_back( - EventRevokerGuard{control->MouseMoveEvent()->Direct()->AddHandler( - [this](event::MouseEventArgs& args) { - if (this->select_down_button_.has_value()) { - const auto text_render_object = - this->text_control_->GetTextRenderObject(); - const auto result = text_render_object->TextHitTest( - text_render_object->FromRootToContent(args.GetPoint())); - const auto position = result.position + (result.trailing ? 1 : 0); - this->caret_position_ = position; - log::Debug("Text select range: {} : {}.", position, - this->select_start_position_); - this->text_control_->GetTextRenderObject()->SetSelectionRange( - TextRange::FromTwoSides( - static_cast<unsigned>(position), - static_cast<unsigned>(this->select_start_position_))); - this->text_control_->GetTextRenderObject()->InvalidatePaint(); - this->text_control_->GetCaretRenderObject()->InvalidatePaint(); - } - })}); + : control_(control), text_control_(text_control) {} - event_revoker_guards_.push_back( - EventRevokerGuard{control->MouseUpEvent()->Direct()->AddHandler( - [this](event::MouseButtonEventArgs& args) { - if (this->select_down_button_.has_value() && - this->select_down_button_.value() == args.GetButton()) { - this->control_->ReleaseMouse(); - this->select_down_button_ = std::nullopt; - log::Debug("End selecting text."); - } - })}); +TextControlService::~TextControlService() { + if (enable_ && caret_visible_) TearDownCaretTimer(); } -TextControlService::~TextControlService() { TearDownCaretTimer(); } +void TextControlService::SetEnabled(bool enable) { + if (enable == enable_) return; + if (enable) { + AbortSelection(); + SetupHandlers(); + if (caret_visible_) { + SetupCaretTimer(); + } + } else { + event_revoker_guards_.clear(); + if (caret_visible_) { + TearDownCaretTimer(); + } + } +} void TextControlService::SetCaretVisible(bool visible) { - if (visible) { - SetupCaretTimer(); + if (visible == caret_visible_) return; + + if (enable_) { + if (visible) { + SetupCaretTimer(); + } } else { TearDownCaretTimer(); } -} +} // namespace cru::ui::controls void TextControlService::DrawCaret(platform::graph::IPainter* painter) { if (caret_show_) { @@ -92,10 +64,19 @@ void TextControlService::DrawCaret(platform::graph::IPainter* painter) { } } -void TextControlService::SetupCaretTimer() { - if (caret_visible_) return; +void TextControlService::AbortSelection() { + if (select_down_button_.has_value()) { + control_->ReleaseMouse(); + select_down_button_ = std::nullopt; + } + text_control_->GetTextRenderObject()->SetSelectionRange(std::nullopt); +} - caret_visible_ = true; +void TextControlService::SetupCaretTimer() { +#ifdef CRU_DEBUG + assert(!caret_timer_set_); + caret_timer_set_ = true; +#endif caret_timer_tag_ = platform::native::IUiApplication::GetInstance()->SetInterval( std::chrono::milliseconds(caret_blink_duration), [this] { @@ -105,9 +86,80 @@ void TextControlService::SetupCaretTimer() { } void TextControlService::TearDownCaretTimer() { - if (!caret_visible_) return; - caret_visible_ = false; +#ifdef CRU_DEBUG + assert(!caret_timer_set_); + caret_timer_set_ = false; +#endif platform::native::IUiApplication::GetInstance()->CancelTimer( caret_timer_tag_); } + +void TextControlService::SetupHandlers() { + assert(event_revoker_guards_.empty()); + event_revoker_guards_.push_back( + EventRevokerGuard{control_->MouseMoveEvent()->Direct()->AddHandler( + std::bind(&TextControlService::MouseMoveHandler, this, + std::placeholders::_1))}); + event_revoker_guards_.push_back( + EventRevokerGuard{control_->MouseDownEvent()->Direct()->AddHandler( + std::bind(&TextControlService::MouseDownHandler, this, + std::placeholders::_1))}); + event_revoker_guards_.push_back(EventRevokerGuard{ + control_->MouseUpEvent()->Direct()->AddHandler(std::bind( + &TextControlService::MouseUpHandler, this, std::placeholders::_1))}); + event_revoker_guards_.push_back( + EventRevokerGuard{control_->LoseFocusEvent()->Direct()->AddHandler( + std::bind(&TextControlService::LoseFocusHandler, this, + std::placeholders::_1))}); +} + +void TextControlService::MouseMoveHandler(event::MouseEventArgs& args) { + if (this->select_down_button_.has_value()) { + const auto text_render_object = this->text_control_->GetTextRenderObject(); + const auto result = text_render_object->TextHitTest( + text_render_object->FromRootToContent(args.GetPoint())); + const auto position = result.position + (result.trailing ? 1 : 0); + this->caret_position_ = position; + log::Debug( + "TextControlService: Text selection changed on mouse move, range: {}, " + "{}.", + position, this->select_start_position_); + this->text_control_->GetTextRenderObject()->SetSelectionRange( + TextRange::FromTwoSides( + static_cast<unsigned>(position), + static_cast<unsigned>(this->select_start_position_))); + this->text_control_->GetTextRenderObject()->InvalidatePaint(); + this->text_control_->GetCaretRenderObject()->InvalidatePaint(); + } +} + +void TextControlService::MouseDownHandler(event::MouseButtonEventArgs& args) { + if (this->select_down_button_.has_value()) { + return; + } else { + if (!this->control_->CaptureMouse()) return; + if (!this->control_->RequestFocus()) return; + const auto text_render_object = this->text_control_->GetTextRenderObject(); + this->select_down_button_ = args.GetButton(); + const auto result = text_render_object->TextHitTest( + text_render_object->FromRootToContent(args.GetPoint())); + const auto position = result.position + (result.trailing ? 1 : 0); + this->select_start_position_ = position; + log::Debug("TextControlService: Begin to select text, start position: {}.", + position); + } +} + +void TextControlService::MouseUpHandler(event::MouseButtonEventArgs& args) { + if (this->select_down_button_.has_value() && + this->select_down_button_.value() == args.GetButton()) { + this->control_->ReleaseMouse(); + this->select_down_button_ = std::nullopt; + log::Debug("TextControlService: End selecting text."); + } +} + +void TextControlService::LoseFocusHandler(event::FocusChangeEventArgs& args) { + if (!args.IsWindow()) this->AbortSelection(); +} } // namespace cru::ui::controls |