aboutsummaryrefslogtreecommitdiff
path: root/src/ui/controls
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-04-24 00:03:16 +0800
committercrupest <crupest@outlook.com>2020-04-24 00:03:16 +0800
commit75ff8a6a05afd02aaadf7e3049b0a0e305241182 (patch)
tree5444bbb3ef80036cc38a827b8ccf03f48b310728 /src/ui/controls
parent922d7f6c96f81a33538900f8a8992a5b6f640874 (diff)
downloadcru-75ff8a6a05afd02aaadf7e3049b0a0e305241182.tar.gz
cru-75ff8a6a05afd02aaadf7e3049b0a0e305241182.tar.bz2
cru-75ff8a6a05afd02aaadf7e3049b0a0e305241182.zip
...
Diffstat (limited to 'src/ui/controls')
-rw-r--r--src/ui/controls/text_block.cpp24
-rw-r--r--src/ui/controls/text_box.cpp27
-rw-r--r--src/ui/controls/text_control_service.hpp111
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();
}
}