diff options
Diffstat (limited to 'src/ui/controls')
-rw-r--r-- | src/ui/controls/text_box.cpp | 70 | ||||
-rw-r--r-- | src/ui/controls/text_box.h | 8 | ||||
-rw-r--r-- | src/ui/controls/text_control.cpp | 13 |
3 files changed, 73 insertions, 18 deletions
diff --git a/src/ui/controls/text_box.cpp b/src/ui/controls/text_box.cpp index 30b9069a..54b2f7ab 100644 --- a/src/ui/controls/text_box.cpp +++ b/src/ui/controls/text_box.cpp @@ -67,16 +67,47 @@ namespace cru::ui::controls Control::OnKeyDownCore(args); if (args.GetVirtualCode() == VK_LEFT && caret_position_ > 0) { - ClearSelection(); - caret_position_--; + if (IsKeyDown(VK_SHIFT)) + { + if (GetCaretSelectionSide()) + ShiftLeftSelectionRange(-1); + else + ShiftRightSelectionRange(-1); + } + else + { + const auto selection = GetSelectedRange(); + if (selection.has_value()) + { + ClearSelection(); + caret_position_ = selection.value().position; + } + else + caret_position_--; + } Repaint(); } if (args.GetVirtualCode() == VK_RIGHT && caret_position_ < GetText().size()) { - ClearSelection(); - caret_position_++; - Repaint(); + if (IsKeyDown(VK_SHIFT)) + { + if (GetCaretSelectionSide()) + ShiftLeftSelectionRange(1); + else + ShiftRightSelectionRange(1); + } + else + { + const auto selection = GetSelectedRange(); + if (selection.has_value()) + { + ClearSelection(); + caret_position_ = selection.value().position + selection.value().count; + } + else + caret_position_++; + } } } @@ -138,4 +169,33 @@ namespace cru::ui::controls caret_position_ = position; Repaint(); } + + bool TextBox::GetCaretSelectionSide() const + { + const auto selection = TextRange::ToTwoSides(GetSelectedRange(), caret_position_); + if (selection.first == caret_position_) + return true; + if (selection.second == caret_position_) + return false; + assert(false); + return true; + } + + void TextBox::ShiftLeftSelectionRange(const int count) + { + const auto selection_range_side = TextRange::ToTwoSides(GetSelectedRange(), caret_position_); + int new_left = selection_range_side.first + count; + new_left = new_left < 0 ? 0 : new_left; // at least 0 + caret_position_ = new_left; + SetSelectedRange(TextRange::FromTwoSides(static_cast<unsigned>(new_left), selection_range_side.second)); + } + + void TextBox::ShiftRightSelectionRange(const int count) + { + const auto selection_range_side = TextRange::ToTwoSides(GetSelectedRange(), caret_position_); + int new_right = selection_range_side.second + count; + new_right = new_right < 0 ? 0 : new_right; // at least 0 + caret_position_ = new_right; + SetSelectedRange(TextRange::FromTwoSides(selection_range_side.first, static_cast<unsigned>(new_right))); + } } diff --git a/src/ui/controls/text_box.h b/src/ui/controls/text_box.h index 540ac758..37e04835 100644 --- a/src/ui/controls/text_box.h +++ b/src/ui/controls/text_box.h @@ -36,7 +36,13 @@ namespace cru::ui::controls void OnKeyDownCore(events::KeyEventArgs& args) override final; void OnCharCore(events::CharEventArgs& args) override final; - void RequestChangeCaretPosition(unsigned position) override; + void RequestChangeCaretPosition(unsigned position) override final; + + private: + // return true if left + bool GetCaretSelectionSide() const; + void ShiftLeftSelectionRange(int count); + void ShiftRightSelectionRange(int count); private: unsigned caret_position_ = 0; diff --git a/src/ui/controls/text_control.cpp b/src/ui/controls/text_control.cpp index ee5b253d..3c5d7c33 100644 --- a/src/ui/controls/text_control.cpp +++ b/src/ui/controls/text_control.cpp @@ -162,18 +162,7 @@ namespace cru::ui::controls { const auto hit_test_result = TextLayoutHitTest(text_layout_.Get(), args.GetPoint(this), false).value(); RequestChangeCaretPosition(hit_test_result); - if (hit_test_result > mouse_down_position_) - { - selected_range_ = TextRange(mouse_down_position_, hit_test_result - mouse_down_position_); - } - else if (hit_test_result < mouse_down_position_) - { - selected_range_ = TextRange(hit_test_result, mouse_down_position_ - hit_test_result); - } - else - { - selected_range_ = std::nullopt; - } + selected_range_ = TextRange::FromTwoSides(hit_test_result, mouse_down_position_); Repaint(); } } |