aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/ui/UiHost.hpp6
-rw-r--r--src/ui/UiHost.cpp10
-rw-r--r--src/ui/controls/TextControlService.hpp12
3 files changed, 19 insertions, 9 deletions
diff --git a/include/cru/ui/UiHost.hpp b/include/cru/ui/UiHost.hpp
index 01791de6..2437b967 100644
--- a/include/cru/ui/UiHost.hpp
+++ b/include/cru/ui/UiHost.hpp
@@ -1,4 +1,5 @@
#pragma once
+#include <functional>
#include "Base.hpp"
#include "cru/common/Event.hpp"
@@ -110,6 +111,10 @@ class UiHost : public Object, public SelfResolvable<UiHost> {
void SetRetainAfterDestroy(bool destroy) { retain_after_destroy_ = destroy; }
+ // Is layout is invalid, wait for relayout and then run the action. Otherwist
+ // run it right now.
+ void RunAfterLayoutStable(std::function<void()> action);
+
private:
//*************** region: native messages ***************
void OnNativeDestroy(platform::native::INativeWindow* window, std::nullptr_t);
@@ -148,6 +153,7 @@ class UiHost : public Object, public SelfResolvable<UiHost> {
bool need_layout_ = false;
Event<AfterLayoutEventArgs> after_layout_event_;
+ std::vector<std::function<void()> > after_layout_stable_action_;
std::shared_ptr<platform::native::INativeWindowResolver>
native_window_resolver_;
diff --git a/src/ui/UiHost.cpp b/src/ui/UiHost.cpp
index d3564619..ccc5fea0 100644
--- a/src/ui/UiHost.cpp
+++ b/src/ui/UiHost.cpp
@@ -193,6 +193,8 @@ void UiHost::Relayout() {
: render::MeasureSize::NotSpecified()},
render::MeasureSize::NotSpecified());
root_render_object_->Layout(Point{});
+ for (auto& action : after_layout_stable_action_) action();
+ after_layout_stable_action_.clear();
after_layout_event_.Raise(AfterLayoutEventArgs{});
log::TagDebug(log_tag, u"A relayout is finished.");
}
@@ -249,6 +251,14 @@ bool UiHost::CaptureMouseFor(Control* control) {
Control* UiHost::GetMouseCaptureControl() { return mouse_captured_control_; }
+void UiHost::RunAfterLayoutStable(std::function<void()> action) {
+ if (need_layout_) {
+ after_layout_stable_action_.push_back(std::move(action));
+ } else {
+ action();
+ }
+}
+
void UiHost::OnNativeDestroy(INativeWindow* window, std::nullptr_t) {
CRU_UNUSED(window)
native_window_destroyed_ = true;
diff --git a/src/ui/controls/TextControlService.hpp b/src/ui/controls/TextControlService.hpp
index 04807c30..376f9177 100644
--- a/src/ui/controls/TextControlService.hpp
+++ b/src/ui/controls/TextControlService.hpp
@@ -206,16 +206,12 @@ class TextControlService : public Object {
SetSelection(GetSelection().GetStart() + text.size());
}
- void ScrollToCaret(bool next_tick = true) {
- if (next_tick) {
- scroll_to_caret_timer_canceler_.Reset(
- GetUiApplication()->GetInstance()->SetImmediate(
- [this]() { this->ScrollToCaret(false); }));
- } else {
+ void ScrollToCaret() {
+ this->control_->GetUiHost()->RunAfterLayoutStable([this]() {
const auto caret_rect = this->GetTextRenderObject()->GetCaretRect();
this->GetScrollRenderObject()->ScrollToContain(caret_rect,
Thickness{5.f});
- }
+ });
}
private:
@@ -453,8 +449,6 @@ class TextControlService : public Object {
ShortcutHub shortcut_hub_;
- platform::native::TimerAutoCanceler scroll_to_caret_timer_canceler_;
-
// nullopt means not selecting
std::optional<MouseButton> select_down_button_;