diff options
author | crupest <crupest@outlook.com> | 2020-09-11 11:17:56 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-09-11 11:17:56 +0800 |
commit | 93b8a62d28f9427f0979d62b71f12fb2858064ee (patch) | |
tree | 8f77e88a2a48db2a4e9fe72e5c85088f8d659a7f | |
parent | 65ca046989cd641da65b754bfa1c99f5e54b219a (diff) | |
download | cru-93b8a62d28f9427f0979d62b71f12fb2858064ee.tar.gz cru-93b8a62d28f9427f0979d62b71f12fb2858064ee.tar.bz2 cru-93b8a62d28f9427f0979d62b71f12fb2858064ee.zip |
...
-rw-r--r-- | demos/main/main.cpp | 3 | ||||
-rw-r--r-- | include/cru/common/Bitmask.hpp | 2 | ||||
-rw-r--r-- | include/cru/platform/GraphBase.hpp | 2 | ||||
-rw-r--r-- | include/cru/platform/graph/TextLayout.hpp | 1 | ||||
-rw-r--r-- | include/cru/platform/native/Keyboard.hpp | 10 | ||||
-rw-r--r-- | include/cru/ui/render/TextRenderObject.hpp | 1 | ||||
-rw-r--r-- | include/cru/win/graph/direct/TextLayout.hpp | 1 | ||||
-rw-r--r-- | src/ui/controls/TextBox.cpp | 2 | ||||
-rw-r--r-- | src/ui/controls/TextControlService.hpp | 64 | ||||
-rw-r--r-- | src/ui/render/TextRenderObject.cpp | 4 | ||||
-rw-r--r-- | src/win/graph/direct/TextLayout.cpp | 2 | ||||
-rw-r--r-- | src/win/native/Keyboard.cpp | 6 |
12 files changed, 88 insertions, 10 deletions
diff --git a/demos/main/main.cpp b/demos/main/main.cpp index a0d4cd88..82038731 100644 --- a/demos/main/main.cpp +++ b/demos/main/main.cpp @@ -53,6 +53,9 @@ int main() { text_block4->SetText(u"Hello World!!!"); flex_layout->AddChild(text_block4, 2); + const auto text_box = TextBox::Create(); + flex_layout->AddChild(text_box, 3); + window->GetUiHost()->GetNativeWindowResolver()->Resolve()->SetVisible(true); return application->Run(); diff --git a/include/cru/common/Bitmask.hpp b/include/cru/common/Bitmask.hpp index ddfdc86b..c1b6443a 100644 --- a/include/cru/common/Bitmask.hpp +++ b/include/cru/common/Bitmask.hpp @@ -35,7 +35,7 @@ struct Bitmask final { bool operator!=(Bitmask rhs) const { return this->value != rhs.value; } explicit operator TUnderlying() const { return value; } - explicit operator bool() const { return value != 0; } + operator bool() const { return value != 0; } TUnderlying value; }; diff --git a/include/cru/platform/GraphBase.hpp b/include/cru/platform/GraphBase.hpp index e476e3cd..9f3f8393 100644 --- a/include/cru/platform/GraphBase.hpp +++ b/include/cru/platform/GraphBase.hpp @@ -258,6 +258,8 @@ struct TextRange final { gsl::index GetStart() const { return position; } gsl::index GetEnd() const { return position + count; } + void SetEnd(gsl::index new_end) { count = new_end - position; } + TextRange Normalize() const { auto result = *this; if (result.count < 0) { diff --git a/include/cru/platform/graph/TextLayout.hpp b/include/cru/platform/graph/TextLayout.hpp index 7dd20987..a101983f 100644 --- a/include/cru/platform/graph/TextLayout.hpp +++ b/include/cru/platform/graph/TextLayout.hpp @@ -7,6 +7,7 @@ namespace cru::platform::graph { struct ITextLayout : virtual IGraphResource { virtual std::u16string GetText() = 0; + virtual std::u16string_view GetTextView() = 0; virtual void SetText(std::u16string new_text) = 0; virtual std::shared_ptr<IFont> GetFont() = 0; diff --git a/include/cru/platform/native/Keyboard.hpp b/include/cru/platform/native/Keyboard.hpp index 26a1409d..83c61bcc 100644 --- a/include/cru/platform/native/Keyboard.hpp +++ b/include/cru/platform/native/Keyboard.hpp @@ -112,9 +112,9 @@ struct TagKeyModifier {}; using KeyModifier = Bitmask<details::TagKeyModifier>; -namespace key_modifiers { -constexpr KeyModifier shift{0b1}; -constexpr KeyModifier ctrl{0b10}; -constexpr KeyModifier alt{0b100}; -} // namespace key_modifiers +struct KeyModifiers { + static constexpr KeyModifier shift{0b1}; + static constexpr KeyModifier ctrl{0b10}; + static constexpr KeyModifier alt{0b100}; +}; } // namespace cru::platform::native diff --git a/include/cru/ui/render/TextRenderObject.hpp b/include/cru/ui/render/TextRenderObject.hpp index 0b276415..3be42bbb 100644 --- a/include/cru/ui/render/TextRenderObject.hpp +++ b/include/cru/ui/render/TextRenderObject.hpp @@ -35,6 +35,7 @@ class TextRenderObject : public RenderObject { ~TextRenderObject() override; std::u16string GetText() const; + std::u16string_view GetTextView() const; void SetText(std::u16string new_text); std::shared_ptr<platform::graph::IBrush> GetBrush() const { return brush_; } diff --git a/include/cru/win/graph/direct/TextLayout.hpp b/include/cru/win/graph/direct/TextLayout.hpp index c53cf655..016009ab 100644 --- a/include/cru/win/graph/direct/TextLayout.hpp +++ b/include/cru/win/graph/direct/TextLayout.hpp @@ -29,6 +29,7 @@ class DWriteTextLayout : public DirectGraphResource, public: std::u16string GetText() override; + std::u16string_view GetTextView() override; void SetText(std::u16string new_text) override; std::shared_ptr<IFont> GetFont() override; diff --git a/src/ui/controls/TextBox.cpp b/src/ui/controls/TextBox.cpp index b25e3bcb..2bc4cf95 100644 --- a/src/ui/controls/TextBox.cpp +++ b/src/ui/controls/TextBox.cpp @@ -32,10 +32,12 @@ TextBox::TextBox() border_render_object_->SetAttachedControl(this); scroll_render_object_->SetAttachedControl(this); text_render_object_->SetAttachedControl(this); + text_render_object_->SetMinSize(Size{50, 20}); service_ = std::make_unique<TextControlService<TextBox>>(this); service_->SetEnabled(true); service_->SetCaretVisible(true); + service_->SetEditable(true); GainFocusEvent()->Direct()->AddHandler([this](event::FocusChangeEventArgs&) { this->service_->SetEnabled(true); diff --git a/src/ui/controls/TextControlService.hpp b/src/ui/controls/TextControlService.hpp index 41959f9d..0d05f2c3 100644 --- a/src/ui/controls/TextControlService.hpp +++ b/src/ui/controls/TextControlService.hpp @@ -1,6 +1,7 @@ #pragma once #include "../Helper.hpp" #include "cru/common/Logger.hpp" +#include "cru/common/StringUtil.hpp" #include "cru/platform/graph/Font.hpp" #include "cru/platform/graph/Painter.hpp" #include "cru/platform/native/UiApplication.hpp" @@ -40,6 +41,7 @@ class TextControlService : public Object { void SetEnabled(bool enable) { if (enable == this->enable_) return; + this->enable_ = enable; if (enable) { this->SetupHandlers(); if (this->caret_visible_) { @@ -52,6 +54,10 @@ class TextControlService : public Object { } } + bool IsEditable() { return this->editable_; } + + void SetEditable(bool editable) { this->editable_ = editable; } + bool IsCaretVisible() { return caret_visible_; } void SetCaretVisible(bool visible) { @@ -218,7 +224,62 @@ class TextControlService : public Object { } } - void KeyDownHandler(event::KeyEventArgs& args) { CRU_UNUSED(args); } + void KeyDownHandler(event::KeyEventArgs& args) { + const auto key_code = args.GetKeyCode(); + using cru::platform::native::KeyCode; + using cru::platform::native::KeyModifiers; + + switch (key_code) { + case KeyCode::Left: { + const auto key_modifier = args.GetKeyModifier(); + const bool shift = key_modifier & KeyModifiers::shift; + auto text = this->GetTextRenderObject()->GetTextView(); + if (shift) { + auto selection = this->GetSelection(); + if (selection) { + gsl::index new_position; + Utf16PreviousCodePoint(text, selection->GetEnd(), &new_position); + selection->SetEnd(new_position); + this->SetSelection(selection); + } else { + const auto caret = this->GetCaretPosition(); + gsl::index new_position; + Utf16PreviousCodePoint(text, caret, &new_position); + this->SetSelection(TextRange::FromTwoSides(caret, new_position)); + } + } else { + const auto caret = this->GetCaretPosition(); + gsl::index new_position; + Utf16PreviousCodePoint(text, caret, &new_position); + this->SetCaretPosition(new_position); + } + } break; + case KeyCode::Right: { + const auto key_modifier = args.GetKeyModifier(); + const bool shift = key_modifier & KeyModifiers::shift; + auto text = this->GetTextRenderObject()->GetTextView(); + if (shift) { + auto selection = this->GetSelection(); + if (selection) { + gsl::index new_position; + Utf16NextCodePoint(text, selection->GetEnd(), &new_position); + selection->SetEnd(new_position); + this->SetSelection(selection); + } else { + const auto caret = this->GetCaretPosition(); + gsl::index new_position; + Utf16PreviousCodePoint(text, caret, &new_position); + this->SetSelection(TextRange::FromTwoSides(caret, new_position)); + } + } else { + const auto caret = this->GetCaretPosition(); + gsl::index new_position; + Utf16NextCodePoint(text, caret, &new_position); + this->SetCaretPosition(new_position); + } + } + } + } void KeyUpHandler(event::KeyEventArgs& args) { CRU_UNUSED(args); } @@ -231,6 +292,7 @@ class TextControlService : public Object { std::vector<EventRevokerGuard> event_revoker_guards_; bool enable_ = false; + bool editable_ = false; bool caret_visible_ = false; long long caret_timer_id_ = -1; diff --git a/src/ui/render/TextRenderObject.cpp b/src/ui/render/TextRenderObject.cpp index cd248cea..cecbe1f3 100644 --- a/src/ui/render/TextRenderObject.cpp +++ b/src/ui/render/TextRenderObject.cpp @@ -37,6 +37,10 @@ std::u16string TextRenderObject::GetText() const { return text_layout_->GetText(); } +std::u16string_view TextRenderObject::GetTextView() const { + return text_layout_->GetTextView(); +} + void TextRenderObject::SetText(std::u16string new_text) { text_layout_->SetText(std::move(new_text)); } diff --git a/src/win/graph/direct/TextLayout.cpp b/src/win/graph/direct/TextLayout.cpp index 7b5b230f..0d4a6392 100644 --- a/src/win/graph/direct/TextLayout.cpp +++ b/src/win/graph/direct/TextLayout.cpp @@ -26,6 +26,8 @@ DWriteTextLayout::~DWriteTextLayout() = default; std::u16string DWriteTextLayout::GetText() { return text_; } +std::u16string_view DWriteTextLayout::GetTextView() { return text_; } + void DWriteTextLayout::SetText(std::u16string new_text) { text_.swap(new_text); ThrowIfFailed(GetDirectFactory()->GetDWriteFactory()->CreateTextLayout( diff --git a/src/win/native/Keyboard.cpp b/src/win/native/Keyboard.cpp index aa22e4a4..929ca737 100644 --- a/src/win/native/Keyboard.cpp +++ b/src/win/native/Keyboard.cpp @@ -66,9 +66,9 @@ KeyCode VirtualKeyToKeyCode(int virtual_key) { KeyModifier RetrieveKeyMofifier() { KeyModifier result{0}; - if (::GetKeyState(VK_SHIFT) < 0) result |= key_modifiers::shift; - if (::GetKeyState(VK_CONTROL) < 0) result |= key_modifiers::ctrl; - if (::GetKeyState(VK_MENU) < 0) result |= key_modifiers::alt; + if (::GetKeyState(VK_SHIFT) < 0) result |= KeyModifiers::shift; + if (::GetKeyState(VK_CONTROL) < 0) result |= KeyModifiers::ctrl; + if (::GetKeyState(VK_MENU) < 0) result |= KeyModifiers::alt; return result; } } // namespace cru::platform::native::win |