From 75ff8a6a05afd02aaadf7e3049b0a0e305241182 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 24 Apr 2020 00:03:16 +0800 Subject: ... --- src/ui/controls/text_block.cpp | 24 +------ src/ui/controls/text_box.cpp | 27 ++------ src/ui/controls/text_control_service.hpp | 111 ++++++++++++------------------- 3 files changed, 53 insertions(+), 109 deletions(-) (limited to 'src/ui/controls') diff --git a/src/ui/controls/text_block.cpp b/src/ui/controls/text_block.cpp index 1c20540d..a3ec9f54 100644 --- a/src/ui/controls/text_block.cpp +++ b/src/ui/controls/text_block.cpp @@ -11,24 +11,14 @@ using render::CanvasRenderObject; using render::StackLayoutRenderObject; using render::TextRenderObject; -TextBlock::TextBlock() - : root_render_object_(new StackLayoutRenderObject()), - text_render_object_(), - caret_render_object_(new CanvasRenderObject()) { +TextBlock::TextBlock() { const auto theme_resources = UiManager::GetInstance()->GetThemeResources(); text_render_object_ = std::make_unique( theme_resources->text_brush, theme_resources->default_font, - theme_resources->text_selection_brush); + theme_resources->text_selection_brush, theme_resources->caret_brush); - root_render_object_->AddChild(text_render_object_.get(), 0); - root_render_object_->AddChild(caret_render_object_.get(), 1); - - root_render_object_->SetAttachedControl(this); text_render_object_->SetAttachedControl(this); - caret_render_object_->SetAttachedControl(this); - - caret_brush_ = theme_resources->caret_brush; service_ = std::make_unique>(this); service_->SetEnabled(true); @@ -37,7 +27,7 @@ TextBlock::TextBlock() TextBlock::~TextBlock() = default; render::RenderObject* TextBlock::GetRenderObject() const { - return root_render_object_.get(); + return text_render_object_.get(); } std::string TextBlock::GetText() const { @@ -51,12 +41,4 @@ void TextBlock::SetText(std::string text) { render::TextRenderObject* TextBlock::GetTextRenderObject() { return text_render_object_.get(); } - -render::CanvasRenderObject* TextBlock::GetCaretRenderObject() { - return caret_render_object_.get(); -} - -std::shared_ptr TextBlock::GetCaretBrush() { - return caret_brush_; -} } // namespace cru::ui::controls diff --git a/src/ui/controls/text_box.cpp b/src/ui/controls/text_box.cpp index 99164b9b..7b63eea1 100644 --- a/src/ui/controls/text_box.cpp +++ b/src/ui/controls/text_box.cpp @@ -13,29 +13,22 @@ using render::CanvasRenderObject; using render::StackLayoutRenderObject; using render::TextRenderObject; -TextBox::TextBox() - : border_render_object_(new BorderRenderObject()), - stack_layout_render_object_(new StackLayoutRenderObject()), - text_render_object_(), - caret_render_object_(new CanvasRenderObject()), - service_(new TextControlService(this)) { +TextBox::TextBox() : border_render_object_(new BorderRenderObject()) { const auto theme_resources = UiManager::GetInstance()->GetThemeResources(); - caret_brush_ = theme_resources->caret_brush; border_style_ = theme_resources->text_box_border_style; text_render_object_ = std::make_unique( theme_resources->text_brush, theme_resources->default_font, - theme_resources->text_selection_brush); + theme_resources->text_selection_brush, theme_resources->caret_brush); - border_render_object_->AddChild(stack_layout_render_object_.get(), 0); - stack_layout_render_object_->AddChild(text_render_object_.get(), 0); - stack_layout_render_object_->AddChild(caret_render_object_.get(), 1); + border_render_object_->AddChild(text_render_object_.get(), 0); border_render_object_->SetAttachedControl(this); - stack_layout_render_object_->SetAttachedControl(this); text_render_object_->SetAttachedControl(this); - caret_render_object_->SetAttachedControl(this); + + service_ = std::make_unique>(this); + service_->SetEnabled(true); GainFocusEvent()->Direct()->AddHandler([this](event::FocusChangeEventArgs&) { this->service_->SetEnabled(true); @@ -54,14 +47,6 @@ render::TextRenderObject* TextBox::GetTextRenderObject() { return text_render_object_.get(); } -render::CanvasRenderObject* TextBox::GetCaretRenderObject() { - return caret_render_object_.get(); -} - -std::shared_ptr TextBox::GetCaretBrush() { - return caret_brush_; -} - const TextBoxBorderStyle& TextBox::GetBorderStyle() { return border_style_; } void TextBox::SetBorderStyle(TextBoxBorderStyle border_style) { diff --git a/src/ui/controls/text_control_service.hpp b/src/ui/controls/text_control_service.hpp index 0da8abed..57a6efa7 100644 --- a/src/ui/controls/text_control_service.hpp +++ b/src/ui/controls/text_control_service.hpp @@ -1,4 +1,5 @@ #pragma once +#include "../helper.hpp" #include "cru/common/logger.hpp" #include "cru/platform/graph/font.hpp" #include "cru/platform/graph/painter.hpp" @@ -15,8 +16,6 @@ constexpr long long caret_blink_duration = 500; // TControl should inherits `Control` and has following methods: // ``` // render::TextRenderObject* GetTextRenderObject(); -// render::CanvasRenderObject* GetCaretRenderObject(); -// std::shared_ptr GetCaretBrush(); // ``` template class TextControlService : public Object { @@ -44,8 +43,8 @@ class TextControlService : public Object { private: void AbortSelection(); - void SetupCaretTimer(); - void TearDownCaretTimer(); + void SetupCaret(); + void TearDownCaret(); void SetupHandlers(); @@ -62,12 +61,7 @@ class TextControlService : public Object { bool caret_visible_ = false; int caret_position_ = 0; -#ifdef CRU_DEBUG - bool caret_timer_set_ = false; -#endif - unsigned long caret_timer_tag_; - // this is used for blinking of caret - bool caret_show_ = true; + long long caret_timer_id_ = -1; // nullopt means not selecting std::optional select_down_button_; @@ -82,101 +76,86 @@ TextControlService::TextControlService(TControl* control) template TextControlService::~TextControlService() { - if (enable_ && caret_visible_) TearDownCaretTimer(); + const auto application = GetUiApplication(); + // Don't call TearDownCaret, because it use text render object of control, + // which may be destroyed already. + application->CancelTimer(this->caret_timer_id_); } template void TextControlService::SetEnabled(bool enable) { - if (enable == enable_) return; + if (enable == this->enable_) return; if (enable) { - AbortSelection(); - SetupHandlers(); - if (caret_visible_) { - SetupCaretTimer(); + this->SetupHandlers(); + if (this->caret_visible_) { + this->SetupCaret(); } } else { - event_revoker_guards_.clear(); - if (caret_visible_) { - TearDownCaretTimer(); - } + this->AbortSelection(); + this->event_revoker_guards_.clear(); + this->TearDownCaret(); } } template void TextControlService::SetCaretVisible(bool visible) { - if (visible == caret_visible_) return; + if (visible == this->caret_visible_) return; + + this->caret_visible_ = visible; - if (enable_) { + if (this->enable_) { if (visible) { - SetupCaretTimer(); + this->SetupCaretTimer(); + } else { + this->TearDownCaretTimer(); } - } else { - TearDownCaretTimer(); } } // namespace cru::ui::controls -template -void TextControlService::DrawCaret( - platform::graph::IPainter* painter) { - if (caret_show_) { - const auto text_render_object = control_->GetTextRenderObject(); - const auto point = text_render_object->TextSingleRect( - caret_position_, false); // Maybe cache the result??? - painter->FillRectangle( - Rect{point, - Size{caret_width, text_render_object->GetFont()->GetFontSize()}}, - control_->GetCaretBrush().get()); - } -} - template void TextControlService::AbortSelection() { - if (select_down_button_.has_value()) { - control_->ReleaseMouse(); - select_down_button_ = std::nullopt; + if (this->select_down_button_.has_value()) { + this->control_->ReleaseMouse(); + this->select_down_button_ = std::nullopt; } - control_->GetTextRenderObject()->SetSelectionRange(std::nullopt); + this->control_->GetTextRenderObject()->SetSelectionRange(std::nullopt); } template -void TextControlService::SetupCaretTimer() { -#ifdef CRU_DEBUG - Expects(!caret_timer_set_); - caret_timer_set_ = true; -#endif - caret_timer_tag_ = - platform::native::IUiApplication::GetInstance()->SetInterval( - std::chrono::milliseconds(caret_blink_duration), [this] { - this->caret_show_ = !this->caret_show_; - this->control_->GetCaretRenderObject()->InvalidatePaint(); - }); +void TextControlService::SetupCaret() { + const auto application = GetUiApplication(); + + // Cancel first anyhow for safety. + application->CancelTimer(this->caret_timer_id_); + + this->control_->GetTextRenderObject()->SetDrawCaret(true); + this->caret_timer_id_ = application->SetInterval( + std::chrono::milliseconds(caret_blink_duration), + [this] { this->control_->GetTextRenderObject()->ToggleDrawCaret(); }); } template -void TextControlService::TearDownCaretTimer() { -#ifdef CRU_DEBUG - Expects(!caret_timer_set_); - caret_timer_set_ = false; -#endif - platform::native::IUiApplication::GetInstance()->CancelTimer( - caret_timer_tag_); +void TextControlService::TearDownCaret() { + const auto application = GetUiApplication(); + application->CancelTimer(this->caret_timer_id_); + this->control_->GetTextRenderObject()->SetDrawCaret(false); } template void TextControlService::SetupHandlers() { Expects(event_revoker_guards_.empty()); - event_revoker_guards_.push_back( + this->event_revoker_guards_.push_back( EventRevokerGuard{control_->MouseMoveEvent()->Direct()->AddHandler( std::bind(&TextControlService::MouseMoveHandler, this, std::placeholders::_1))}); - event_revoker_guards_.push_back( + this->event_revoker_guards_.push_back( EventRevokerGuard{control_->MouseDownEvent()->Direct()->AddHandler( std::bind(&TextControlService::MouseDownHandler, this, std::placeholders::_1))}); - event_revoker_guards_.push_back(EventRevokerGuard{ + this->event_revoker_guards_.push_back(EventRevokerGuard{ control_->MouseUpEvent()->Direct()->AddHandler(std::bind( &TextControlService::MouseUpHandler, this, std::placeholders::_1))}); - event_revoker_guards_.push_back( + this->event_revoker_guards_.push_back( EventRevokerGuard{control_->LoseFocusEvent()->Direct()->AddHandler( std::bind(&TextControlService::LoseFocusHandler, this, std::placeholders::_1))}); @@ -199,8 +178,6 @@ void TextControlService::MouseMoveHandler( TextRange::FromTwoSides( static_cast(position), static_cast(this->select_start_position_))); - this->control_->GetTextRenderObject()->InvalidatePaint(); - this->control_->GetCaretRenderObject()->InvalidatePaint(); } } -- cgit v1.2.3