diff --git a/src/DrawingProgram/TextBoxEditTool.cpp b/src/DrawingProgram/TextBoxEditTool.cpp index abf3c04..968acd3 100644 --- a/src/DrawingProgram/TextBoxEditTool.cpp +++ b/src/DrawingProgram/TextBoxEditTool.cpp @@ -259,7 +259,7 @@ void TextBoxEditTool::edit_start(EditTool& editTool, const std::shared_ptrtextBox; cur = std::make_shared(); Vector2f textSelectPos = a->get_mouse_pos(drawP); - textbox->process_mouse_left_button(*cur, textSelectPos, true, false, false); + textbox->process_mouse_left_button(*cur, textSelectPos, 1, false, false); prevData = get_all_data(a); a->d.editing = true; a->textBox->inputChangedTextBox = true; @@ -287,7 +287,7 @@ bool TextBoxEditTool::edit_update(const std::shared_ptr& comp) { bool collidesWithBox = a->collides_with_cam_coords(drawP.world.drawData.cam.c, mousePointCollection); input.text.set_rich_text_box_input(a->textBox, a->cursor, currentMods); - a->textBox->process_mouse_left_button(*a->cursor, a->get_mouse_pos(drawP), drawP.controls.leftClick && collidesWithBox, drawP.controls.leftClickHeld, input.key(InputManager::KEY_GENERIC_LSHIFT).held); + a->textBox->process_mouse_left_button(*a->cursor, a->get_mouse_pos(drawP), (drawP.controls.leftClick && collidesWithBox) ? drawP.world.main.input.mouse.leftClicks : 0, drawP.controls.leftClickHeld, input.key(InputManager::KEY_GENERIC_LSHIFT).held); return true; } diff --git a/src/RichText/TextBox.cpp b/src/RichText/TextBox.cpp index 5cc9430..c9c8d1a 100644 --- a/src/RichText/TextBox.cpp +++ b/src/RichText/TextBox.cpp @@ -173,20 +173,58 @@ void TextBox::process_key_input(Cursor& cur, InputKey in, bool ctrl, bool shift, inputChangedTextBox = true; } -void TextBox::process_mouse_left_button(Cursor& cur, const Vector2f& pos, bool clicked, bool held, bool shift) { - if(clicked || held) { +void TextBox::process_mouse_left_button(Cursor& cur, const Vector2f& pos, int clickCount, bool held, bool shift) { + if(!held) + lastClicksWhileHeld = clickCount; + else + lastClicksWhileHeld = std::max(lastClicksWhileHeld, clickCount); + + if(lastClicksWhileHeld || held) { rebuild(); Cursor oldCursor = cur; cur.pos = get_text_pos_closest_to_point(pos); + if(lastClicksCursorPos != cur.pos && clickCount) { + lastClicksWhileHeld = std::min(1, lastClicksWhileHeld); + lastClicksCursorPos = cur.pos; + } cur.selectionBeginPos = cur.pos; - if(clicked && !shift) - cur.selectionEndPos = cur.selectionBeginPos; + if(lastClicksWhileHeld && !shift) { + if(!cur.selectionEndPosBeforeHeld.has_value()) { + cur.selectionEndPos = cur.selectionBeginPos; + cur.selectionEndPosBeforeHeld = cur.selectionEndPos; + } + if(lastClicksWhileHeld == 3) { + cur.selectionEndPos = cur.selectionEndPosBeforeHeld.value(); + if(cur.selectionBeginPos < cur.selectionEndPos) { + cur.selectionBeginPos.fTextByteIndex = 0; + cur.selectionEndPos.fTextByteIndex = paragraphs[cur.selectionEndPos.fParagraphIndex].text.size(); + } + else { + cur.selectionBeginPos.fTextByteIndex = paragraphs[cur.selectionBeginPos.fParagraphIndex].text.size(); + cur.selectionEndPos.fTextByteIndex = 0; + } + } + else if(lastClicksWhileHeld == 2) { + cur.selectionEndPos = cur.selectionEndPosBeforeHeld.value(); + if(cur.selectionBeginPos < cur.selectionEndPos) { + cur.selectionBeginPos = move(Movement::LEFT_WORD_TIGHT, cur.selectionBeginPos); + cur.selectionEndPos = move(Movement::RIGHT_WORD_TIGHT, cur.selectionEndPos); + } + else { + cur.selectionBeginPos = move(Movement::RIGHT_WORD_TIGHT, cur.selectionBeginPos); + cur.selectionEndPos = move(Movement::LEFT_WORD_TIGHT, cur.selectionEndPos); + } + } + } + cur.previousX = std::nullopt; inputChangedTextBox |= (oldCursor != cur); } + else + cur.selectionEndPosBeforeHeld = std::nullopt; } std::pair TextBox::process_copy(Cursor& cur) { @@ -716,7 +754,8 @@ TextPosition TextBox::move(Movement movement, TextPosition pos, std::optionalisWhitespace(u)) + if(!SkUnicodes::ICU::Make()->isWhitespace(u) || movement == Movement::LEFT_WORD_TIGHT) byteIndexToRet = nextByteIndex; } break; } - case Movement::RIGHT_WORD: { + case Movement::RIGHT_WORD: + case Movement::RIGHT_WORD_TIGHT: { TextPosition endPos = move(Movement::END, {0, 0}); if(pos == endPos) break; @@ -761,7 +801,7 @@ TextPosition TextBox::move(Movement movement, TextPosition pos, std::optionalisWhitespace(u)) + if(!SkUnicodes::ICU::Make()->isWhitespace(u) || movement == Movement::RIGHT_WORD_TIGHT) return get_text_pos_from_byte_pos(fullText, p); } diff --git a/src/RichText/TextBox.hpp b/src/RichText/TextBox.hpp index 153d1e6..bcf186c 100644 --- a/src/RichText/TextBox.hpp +++ b/src/RichText/TextBox.hpp @@ -71,7 +71,9 @@ class TextBox { UP, DOWN, LEFT_WORD, + LEFT_WORD_TIGHT, RIGHT_WORD, + RIGHT_WORD_TIGHT, HOME, END }; @@ -84,6 +86,7 @@ class TextBox { a(pos, selectionBeginPos, selectionEndPos); } std::optional previousX; + std::optional selectionEndPosBeforeHeld; bool operator==(const Cursor& o) const; bool operator!=(const Cursor& o) const; }; @@ -135,7 +138,7 @@ class TextBox { void clear_text(); void set_string(const std::string& str); - void process_mouse_left_button(Cursor& cur, const Vector2f& pos, bool clicked, bool held, bool shift); + void process_mouse_left_button(Cursor& cur, const Vector2f& pos, int clickCount, bool held, bool shift); void process_key_input(Cursor& cur, InputKey in, bool ctrl, bool shift, const std::optional& inputModMap = std::nullopt); std::pair process_copy(Cursor& cur); std::pair process_cut(Cursor& cur); @@ -183,6 +186,9 @@ class TextBox { unsigned tabWidth = 4; std::shared_ptr fontData; + int lastClicksWhileHeld = 0; + TextPosition lastClicksCursorPos{0, 0}; + struct ParagraphData { std::string text; std::unique_ptr p;