diff options
author | crupest <crupest@outlook.com> | 2020-04-24 00:03:16 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-04-24 00:03:16 +0800 |
commit | 75ff8a6a05afd02aaadf7e3049b0a0e305241182 (patch) | |
tree | 5444bbb3ef80036cc38a827b8ccf03f48b310728 /src/ui/controls | |
parent | 922d7f6c96f81a33538900f8a8992a5b6f640874 (diff) | |
download | cru-75ff8a6a05afd02aaadf7e3049b0a0e305241182.tar.gz cru-75ff8a6a05afd02aaadf7e3049b0a0e305241182.tar.bz2 cru-75ff8a6a05afd02aaadf7e3049b0a0e305241182.zip |
...
Diffstat (limited to 'src/ui/controls')
-rw-r--r-- | src/ui/controls/text_block.cpp | 24 | ||||
-rw-r--r-- | src/ui/controls/text_box.cpp | 27 | ||||
-rw-r--r-- | src/ui/controls/text_control_service.hpp | 111 |
3 files changed, 53 insertions, 109 deletions
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<TextRenderObject>( 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<TextControlService<TextBlock>>(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<platform::graph::IBrush> 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<TextBox>(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<TextRenderObject>( 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<TextControlService<TextBox>>(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<platform::graph::IBrush> 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<platform::graph::IBrush> GetCaretBrush(); // ``` template <typename TControl> 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<MouseButton> select_down_button_; @@ -82,101 +76,86 @@ TextControlService<TControl>::TextControlService(TControl* control) template <typename TControl> TextControlService<TControl>::~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 <typename TControl> void TextControlService<TControl>::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 <typename TControl> void TextControlService<TControl>::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 <typename TControl> -void TextControlService<TControl>::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 <typename TControl> void TextControlService<TControl>::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 <typename TControl> -void TextControlService<TControl>::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<TControl>::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 <typename TControl> -void TextControlService<TControl>::TearDownCaretTimer() { -#ifdef CRU_DEBUG - Expects(!caret_timer_set_); - caret_timer_set_ = false; -#endif - platform::native::IUiApplication::GetInstance()->CancelTimer( - caret_timer_tag_); +void TextControlService<TControl>::TearDownCaret() { + const auto application = GetUiApplication(); + application->CancelTimer(this->caret_timer_id_); + this->control_->GetTextRenderObject()->SetDrawCaret(false); } template <typename TControl> void TextControlService<TControl>::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<TControl>::MouseMoveHandler( TextRange::FromTwoSides( static_cast<unsigned>(position), static_cast<unsigned>(this->select_start_position_))); - this->control_->GetTextRenderObject()->InvalidatePaint(); - this->control_->GetCaretRenderObject()->InvalidatePaint(); } } |