diff --git a/escher/include/escher/text_area.h b/escher/include/escher/text_area.h index 41c177a41..51881daeb 100644 --- a/escher/include/escher/text_area.h +++ b/escher/include/escher/text_area.h @@ -131,7 +131,7 @@ protected: ContentView * contentView() { return static_cast(TextInput::contentView()); } private: - void selectUpDown(bool up); + void selectUpDown(bool up, int step); TextAreaDelegate * m_delegate; }; diff --git a/escher/include/escher/text_input.h b/escher/include/escher/text_input.h index 34c75dcd8..0de69538c 100644 --- a/escher/include/escher/text_input.h +++ b/escher/include/escher/text_input.h @@ -98,9 +98,10 @@ protected: return const_cast(nonEditableContentView()); } virtual const ContentView * nonEditableContentView() const = 0; - bool moveCursorLeft(); - bool moveCursorRight(); - bool selectLeftRight(bool left, bool all); // While indicates if all the text on the left/right should be selected + bool moveCursorLeft(int step = 1); + bool moveCursorRight(int step = 1); + // all indicates if all the text on the left/right should be selected + bool selectLeftRight(bool left, bool all, int step = 1); private: virtual void willSetCursorLocation(const char * * location) {} virtual bool privateRemoveEndOfLine(); diff --git a/escher/src/text_area.cpp b/escher/src/text_area.cpp index ab2162a63..2e24fdaad 100644 --- a/escher/src/text_area.cpp +++ b/escher/src/text_area.cpp @@ -106,25 +106,22 @@ bool TextArea::handleEvent(Ion::Events::Event event) { if (handleBoxEvent(event)) { return true; } + int step = Ion::Events::longRepetitionScrollSpeed(); if (event == Ion::Events::ShiftLeft || event == Ion::Events::ShiftRight) { - selectLeftRight(event == Ion::Events::ShiftLeft, false); + selectLeftRight(event == Ion::Events::ShiftLeft, false, step); return true; } - if (event == Ion::Events::ShiftUp ||event == Ion::Events::ShiftDown) { - selectUpDown(event == Ion::Events::ShiftUp); + if (event == Ion::Events::ShiftUp || event == Ion::Events::ShiftDown) { + selectUpDown(event == Ion::Events::ShiftUp, step); return true; } - if (event == Ion::Events::Left) { + if (event == Ion::Events::Left || event == Ion::Events::Right) { if (contentView()->resetSelection()) { return true; } - return TextInput::moveCursorLeft(); - } - if (event == Ion::Events::Right) { - if (contentView()->resetSelection()) { - return true; - } - return TextInput::moveCursorRight(); + return (event == Ion::Events::Left) ? + TextInput::moveCursorLeft(step) : + TextInput::moveCursorRight(step); } if (event.hasText()) { @@ -158,12 +155,9 @@ bool TextArea::handleEvent(Ion::Events::Event event) { deleteSelection(); return true; } - } else if (event == Ion::Events::Up) { + } else if (event == Ion::Events::Up || event == Ion::Events::Down) { contentView()->resetSelection(); - contentView()->moveCursorGeo(0, -1); - } else if (event == Ion::Events::Down) { - contentView()->resetSelection(); - contentView()->moveCursorGeo(0, 1); + contentView()->moveCursorGeo(0, event == Ion::Events::Up ? -step : step); } else if (event == Ion::Events::Clear) { if (!contentView()->selectionIsEmpty()) { deleteSelection(); @@ -565,9 +559,9 @@ void TextArea::ContentView::moveCursorGeo(int deltaX, int deltaY) { setCursorLocation(m_text.pointerAtPosition(Text::Position(p.column() + deltaX, p.line() + deltaY))); } -void TextArea::selectUpDown(bool up) { +void TextArea::selectUpDown(bool up, int step) { const char * previousCursorLocation = contentView()->cursorLocation(); - contentView()->moveCursorGeo(0, up ? -1 : 1); + contentView()->moveCursorGeo(0, up ? -step : step); const char * newCursorLocation = contentView()->cursorLocation(); contentView()->addSelection(up ? newCursorLocation : previousCursorLocation, up ? previousCursorLocation : newCursorLocation); scrollToCursor(); diff --git a/escher/src/text_input.cpp b/escher/src/text_input.cpp index 6e573a045..ccf943ddd 100644 --- a/escher/src/text_input.cpp +++ b/escher/src/text_input.cpp @@ -187,28 +187,46 @@ bool TextInput::removeEndOfLine() { return false; } -bool TextInput::moveCursorLeft() { - if (cursorLocation() <= text()) { - assert(cursorLocation() == text()); - return false; +bool TextInput::moveCursorLeft(int step) { + // Move the cursor to the left step times, or until limit is reached. + int i = 0; + bool canMove = true; + while (canMove && i < step) { + if (cursorLocation() <= text()) { + assert(cursorLocation() == text()); + canMove = false; + } else { + UTF8Decoder decoder(text(), cursorLocation()); + canMove = setCursorLocation(decoder.previousGlyphPosition()); + } + i++; } - UTF8Decoder decoder(text(), cursorLocation()); - return setCursorLocation(decoder.previousGlyphPosition()); + // true is returned if there was at least one successful cursor mouvement + return (i > 1 || canMove); } -bool TextInput::moveCursorRight() { - if (UTF8Helper::CodePointIs(cursorLocation(), UCodePointNull)) { - return false; +bool TextInput::moveCursorRight(int step) { + // Move the cursor to the right step times, or until limit is reached. + int i = 0; + bool canMove = true; + while (canMove && i < step) { + if (UTF8Helper::CodePointIs(cursorLocation(), UCodePointNull)) { + canMove = false; + } else { + UTF8Decoder decoder(cursorLocation()); + canMove = setCursorLocation(decoder.nextGlyphPosition()); + } + i++; } - UTF8Decoder decoder(cursorLocation()); - return setCursorLocation(decoder.nextGlyphPosition()); + // true is returned if there was at least one successful cursor mouvement + return (i > 1 || canMove); } -bool TextInput::selectLeftRight(bool left, bool all) { +bool TextInput::selectLeftRight(bool left, bool all, int step) { const char * cursorLoc = cursorLocation(); const char * nextCursorLoc = nullptr; if (!all) { - bool moved = left ? moveCursorLeft() : moveCursorRight(); + bool moved = left ? moveCursorLeft(step) : moveCursorRight(step); if (!moved) { return false; }