diff options
author | crupest <crupest@outlook.com> | 2020-12-25 15:38:18 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-12-25 15:38:18 +0800 |
commit | da7ad0ff5c5b158be69c6cf9a2c8e9fc9ef2b3cb (patch) | |
tree | 9d58ba66119f5a1f6efa5a9b75c22e0453993a07 /include/cru | |
parent | a14704fbd9b9fb377b7009a9fbe641a9b8d0fdfb (diff) | |
download | cru-da7ad0ff5c5b158be69c6cf9a2c8e9fc9ef2b3cb.tar.gz cru-da7ad0ff5c5b158be69c6cf9a2c8e9fc9ef2b3cb.tar.bz2 cru-da7ad0ff5c5b158be69c6cf9a2c8e9fc9ef2b3cb.zip |
...
Diffstat (limited to 'include/cru')
-rw-r--r-- | include/cru/platform/GraphBase.hpp | 2 | ||||
-rw-r--r-- | include/cru/ui/controls/TextBlock.hpp | 15 | ||||
-rw-r--r-- | include/cru/ui/controls/TextBox.hpp | 12 | ||||
-rw-r--r-- | include/cru/ui/controls/TextHostControlService.hpp | 141 |
4 files changed, 158 insertions, 12 deletions
diff --git a/include/cru/platform/GraphBase.hpp b/include/cru/platform/GraphBase.hpp index 2b40898e..b580ad31 100644 --- a/include/cru/platform/GraphBase.hpp +++ b/include/cru/platform/GraphBase.hpp @@ -277,7 +277,7 @@ struct TextRange final { gsl::index GetStart() const { return position; } gsl::index GetEnd() const { return position + count; } - void AdjustEnd(gsl::index new_end) { count = new_end - position; } + void ChangeEnd(gsl::index new_end) { count = new_end - position; } TextRange Normalize() const { auto result = *this; diff --git a/include/cru/ui/controls/TextBlock.hpp b/include/cru/ui/controls/TextBlock.hpp index 66ebe476..be31816c 100644 --- a/include/cru/ui/controls/TextBlock.hpp +++ b/include/cru/ui/controls/TextBlock.hpp @@ -1,11 +1,10 @@ #pragma once #include "NoChildControl.hpp" -namespace cru::ui::controls { -template <typename TControl> -class TextControlService; +#include "TextHostControlService.hpp" -class TextBlock : public NoChildControl { +namespace cru::ui::controls { +class TextBlock : public NoChildControl, public virtual ITextHostControl { public: static constexpr std::u16string_view control_type = u"TextBlock"; @@ -32,12 +31,14 @@ class TextBlock : public NoChildControl { bool IsSelectable() const; void SetSelectable(bool value); - gsl::not_null<render::TextRenderObject*> GetTextRenderObject(); - render::ScrollRenderObject* GetScrollRenderObject() { return nullptr; } + gsl::not_null<render::TextRenderObject*> GetTextRenderObject() override; + render::ScrollRenderObject* GetScrollRenderObject() override { + return nullptr; + } private: std::unique_ptr<render::TextRenderObject> text_render_object_; - std::unique_ptr<TextControlService<TextBlock>> service_; + std::unique_ptr<TextHostControlService> service_; }; } // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextBox.hpp b/include/cru/ui/controls/TextBox.hpp index 75e7cb65..5693b315 100644 --- a/include/cru/ui/controls/TextBox.hpp +++ b/include/cru/ui/controls/TextBox.hpp @@ -1,6 +1,8 @@ #pragma once #include "NoChildControl.hpp" + #include "IBorderControl.hpp" +#include "TextHostControlService.hpp" #include <memory> @@ -8,7 +10,9 @@ namespace cru::ui::controls { template <typename TControl> class TextControlService; -class TextBox : public NoChildControl, public IBorderControl { +class TextBox : public NoChildControl, + public virtual IBorderControl, + public virtual ITextHostControl { public: static constexpr std::u16string_view control_type = u"TextBox"; @@ -27,8 +31,8 @@ class TextBox : public NoChildControl, public IBorderControl { render::RenderObject* GetRenderObject() const override; - gsl::not_null<render::TextRenderObject*> GetTextRenderObject(); - render::ScrollRenderObject* GetScrollRenderObject(); + gsl::not_null<render::TextRenderObject*> GetTextRenderObject() override; + render::ScrollRenderObject* GetScrollRenderObject() override; void ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) override; @@ -37,6 +41,6 @@ class TextBox : public NoChildControl, public IBorderControl { std::unique_ptr<render::ScrollRenderObject> scroll_render_object_; std::unique_ptr<render::TextRenderObject> text_render_object_; - std::unique_ptr<TextControlService<TextBox>> service_; + std::unique_ptr<TextHostControlService> service_; }; } // namespace cru::ui::controls diff --git a/include/cru/ui/controls/TextHostControlService.hpp b/include/cru/ui/controls/TextHostControlService.hpp new file mode 100644 index 00000000..0bea52c8 --- /dev/null +++ b/include/cru/ui/controls/TextHostControlService.hpp @@ -0,0 +1,141 @@ +#pragma once +#include "Base.hpp" + +#include "cru/platform/gui/InputMethod.hpp" +#include "cru/platform/gui/UiApplication.hpp" +#include "cru/ui/controls/Control.hpp" +#include "cru/ui/helper/ShortcutHub.hpp" + +#include <functional> +#include <string> + +namespace cru::ui::render { +class TextRenderObject; +class ScrollRenderObject; +} // namespace cru::ui::render + +namespace cru::ui::controls { +constexpr int k_default_caret_blink_duration = 500; + +struct ITextHostControl : virtual Interface { + virtual gsl::not_null<render::TextRenderObject*> GetTextRenderObject() = 0; + // May return nullptr. + virtual render::ScrollRenderObject* GetScrollRenderObject() = 0; +}; + +class TextHostControlService : public Object { + CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::controls::TextControlService") + + public: + TextHostControlService(gsl::not_null<Control*> control); + + CRU_DELETE_COPY(TextHostControlService) + CRU_DELETE_MOVE(TextHostControlService) + + ~TextHostControlService() = default; + + public: + bool IsEnabled() { return enable_; } + void SetEnabled(bool enable); + + bool IsEditable() { return this->editable_; } + void SetEditable(bool editable); + + std::u16string GetText() { return this->text_; } + std::u16string_view GetTextView() { return this->text_; } + void SetText(std::u16string text, bool stop_composition = false); + + void InsertText(gsl::index position, std::u16string_view text, + bool stop_composition = false); + void DeleteChar(gsl::index position, bool stop_composition = false); + + // Return the position of deleted character. + gsl::index DeleteCharPrevious(gsl::index position, + bool stop_composition = false); + void DeleteText(TextRange range, bool stop_composition = false); + + void CancelComposition(); + + std::optional<platform::gui::CompositionText> GetCompositionInfo(); + + bool IsCaretVisible() { return caret_visible_; } + void SetCaretVisible(bool visible); + + int GetCaretBlinkDuration() { return caret_blink_duration_; } + void SetCaretBlinkDuration(int milliseconds); + + gsl::index GetCaretPosition() { return selection_.GetEnd(); } + TextRange GetSelection() { return selection_; } + + void SetSelection(gsl::index caret_position); + void SetSelection(TextRange selection, bool scroll_to_caret = true); + + void DeleteSelectedText(); + + // If some text is selected, then they are deleted first. Then insert text + // into caret position. + void ReplaceSelectedText(std::u16string_view text); + + void ScrollToCaret(); + + private: + gsl::not_null<render::TextRenderObject*> GetTextRenderObject(); + render::ScrollRenderObject* GetScrollRenderObject(); + + // May return nullptr. + platform::gui::IInputMethodContext* GetInputMethodContext(); + + void CoerceSelection(); + + void SetupCaret(); + void TearDownCaret(); + + void SyncTextRenderObject(); + + void StartSelection(Index start); + void UpdateSelection(Index new_end); + void AbortSelection(); + + void UpdateInputMethodPosition(); + + template <typename TArgs> + void SetupOneHandler(event::RoutedEvent<TArgs>* (Control::*event)(), + void (TextHostControlService::*handler)( + typename event::RoutedEvent<TArgs>::EventArgs)) { + this->event_guard_ += (this->control_->*event)()->Direct()->AddHandler( + std::bind(handler, this, std::placeholders::_1)); + } + + void SetUpHandlers(); + void TearDownHandlers(); + + void MouseMoveHandler(event::MouseEventArgs& args); + void MouseDownHandler(event::MouseButtonEventArgs& args); + void MouseUpHandler(event::MouseButtonEventArgs& args); + void KeyDownHandler(event::KeyEventArgs& args); + void GainFocusHandler(event::FocusChangeEventArgs& args); + void LoseFocusHandler(event::FocusChangeEventArgs& args); + + private: + gsl::not_null<Control*> control_; + gsl::not_null<ITextHostControl*> text_host_control_; + + EventRevokerListGuard event_guard_; + EventRevokerListGuard input_method_context_event_guard_; + + std::u16string text_; + TextRange selection_; + + bool enable_ = false; + bool editable_ = false; + + bool caret_visible_ = false; + platform::gui::TimerAutoCanceler caret_timer_canceler_; + int caret_blink_duration_ = k_default_caret_blink_duration; + + helper::ShortcutHub shortcut_hub_; + + // true if left mouse is down and selecting + bool mouse_move_selecting_; +}; +} // namespace cru::ui::controls |