From 36820c22929f4fb11892c4fbd52f321cc63a55ad Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 7 Oct 2018 00:49:38 +0800 Subject: Add shift selection, and fix the bug that caret is at wrong position when move with selection. --- src/ui/controls/text_box.cpp | 70 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 5 deletions(-) (limited to 'src/ui/controls/text_box.cpp') 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(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(new_right))); + } } -- cgit v1.2.3