diff options
-rw-r--r-- | include/cru/ui/UiHost.hpp | 6 | ||||
-rw-r--r-- | src/ui/UiHost.cpp | 10 | ||||
-rw-r--r-- | src/ui/controls/TextControlService.hpp | 12 |
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_; |