aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-09-11 11:17:56 +0800
committercrupest <crupest@outlook.com>2020-09-11 11:17:56 +0800
commit93b8a62d28f9427f0979d62b71f12fb2858064ee (patch)
tree8f77e88a2a48db2a4e9fe72e5c85088f8d659a7f
parent65ca046989cd641da65b754bfa1c99f5e54b219a (diff)
downloadcru-93b8a62d28f9427f0979d62b71f12fb2858064ee.tar.gz
cru-93b8a62d28f9427f0979d62b71f12fb2858064ee.tar.bz2
cru-93b8a62d28f9427f0979d62b71f12fb2858064ee.zip
...
-rw-r--r--demos/main/main.cpp3
-rw-r--r--include/cru/common/Bitmask.hpp2
-rw-r--r--include/cru/platform/GraphBase.hpp2
-rw-r--r--include/cru/platform/graph/TextLayout.hpp1
-rw-r--r--include/cru/platform/native/Keyboard.hpp10
-rw-r--r--include/cru/ui/render/TextRenderObject.hpp1
-rw-r--r--include/cru/win/graph/direct/TextLayout.hpp1
-rw-r--r--src/ui/controls/TextBox.cpp2
-rw-r--r--src/ui/controls/TextControlService.hpp64
-rw-r--r--src/ui/render/TextRenderObject.cpp4
-rw-r--r--src/win/graph/direct/TextLayout.cpp2
-rw-r--r--src/win/native/Keyboard.cpp6
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