From 06e783f22802718c1f2bdfa39b31f606af93c4fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Mon, 23 Jan 2023 21:15:45 -0300 Subject: [PATCH] More work in multi cursor, move and selection commands working. select-word reimplemented with multiple cursors. --- include/eepp/ui/doc/textdocument.hpp | 13 ++- src/eepp/ui/doc/textdocument.cpp | 132 +++++++++++++++++++-------- src/eepp/ui/uicodeeditor.cpp | 8 +- src/tools/ecode/ecode.cpp | 5 + 4 files changed, 111 insertions(+), 47 deletions(-) diff --git a/include/eepp/ui/doc/textdocument.hpp b/include/eepp/ui/doc/textdocument.hpp index 3f9d8e6ad..6b9c289bd 100644 --- a/include/eepp/ui/doc/textdocument.hpp +++ b/include/eepp/ui/doc/textdocument.hpp @@ -33,7 +33,7 @@ struct DocumentContentChange { class EE_API TextRanges : public std::vector { public: - bool isValid() { + bool isValid() const { for ( const auto& selection : *this ) { if ( !selection.isValid() ) return false; @@ -41,7 +41,7 @@ class EE_API TextRanges : public std::vector { return true; } - bool exists( const TextRange& range ) { + bool exists( const TextRange& range ) const { for ( const auto& r : *this ) if ( range == r ) return true; @@ -159,7 +159,7 @@ class EE_API TextDocument { TextRange getSelection( bool sort ) const; - const std::vector& getSelections() const; + const TextRanges& getSelections() const; const TextRange& getSelection() const; @@ -210,9 +210,10 @@ class EE_API TextDocument { TextPosition previousChar( TextPosition position ) const; - TextPosition previousWordBoundary( TextPosition position ) const; + TextPosition previousWordBoundary( TextPosition position, + bool ignoreFirstNonWord = true ) const; - TextPosition nextWordBoundary( TextPosition position ) const; + TextPosition nextWordBoundary( TextPosition position, bool ignoreFirstNonWord = true ) const; TextPosition previousSpaceBoundaryInLine( TextPosition position ) const; @@ -520,6 +521,8 @@ class EE_API TextDocument { void setSelection( const size_t& cursorIdx, const TextRange& range ); + void addSelection( const TextRange& selection ); + protected: friend class UndoStack; diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index 56880c81b..f65d07627 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -657,11 +657,18 @@ void TextDocument::setSelection( const size_t& cursorIdx, const TextRange& range setSelection( cursorIdx, range.start(), range.end() ); } +void TextDocument::addSelection( const TextRange& selection ) { + mSelection.emplace_back( selection ); + mergeSelection(); + notifyCursorChanged(); + notifySelectionChanged(); +} + TextRange TextDocument::getSelection( bool sort ) const { return sort ? mSelection.front().normalized() : mSelection.front(); } -const std::vector& TextDocument::getSelections() const { +const TextRanges& TextDocument::getSelections() const { return mSelection; } @@ -906,9 +913,12 @@ TextPosition TextDocument::previousChar( TextPosition position ) const { return positionOffset( position, TextPosition( 0, -1 ) ); } -TextPosition TextDocument::previousWordBoundary( TextPosition position ) const { +TextPosition TextDocument::previousWordBoundary( TextPosition position, + bool ignoreFirstNonWord ) const { auto ch = getChar( positionOffset( position, -1 ) ); bool inWord = !isNonWord( ch ); + if ( !ignoreFirstNonWord && !inWord ) + return position; String::StringBaseType nextChar = 0; do { TextPosition curPos = position; @@ -921,9 +931,12 @@ TextPosition TextDocument::previousWordBoundary( TextPosition position ) const { return position; } -TextPosition TextDocument::nextWordBoundary( TextPosition position ) const { +TextPosition TextDocument::nextWordBoundary( TextPosition position, + bool ignoreFirstNonWord ) const { auto ch = getChar( position ); bool inWord = !isNonWord( ch ); + if ( !ignoreFirstNonWord && !inWord ) + return position; String::StringBaseType nextChar = 0; do { TextPosition curPos = position; @@ -1064,11 +1077,12 @@ void TextDocument::selectTo( int offset ) { } void TextDocument::selectTo( const size_t& cursorIdx, TextPosition position ) { - setSelection( cursorIdx, TextRange( sanitizePosition( position ), getSelection().end() ) ); + setSelection( cursorIdx, + TextRange( sanitizePosition( position ), getSelectionIndex( cursorIdx ).end() ) ); } void TextDocument::selectTo( const size_t& cursorIdx, int offset ) { - const TextRange& range = getSelection(); + const TextRange& range = getSelectionIndex( cursorIdx ); TextPosition posOffset = positionOffset( range.start(), offset ); setSelection( cursorIdx, TextRange( posOffset, range.end() ) ); } @@ -1225,26 +1239,36 @@ void TextDocument::moveToEndOfDoc() { } void TextDocument::moveToStartOfContent() { - TextPosition start = getSelection().start(); - TextPosition indented = startOfContent( getSelection().start() ); - setSelection( indented.column() == start.column() ? TextPosition( start.line(), 0 ) - : indented ); + for ( size_t i = 0; i < mSelection.size(); ++i ) { + TextPosition start = getSelectionIndex( i ).start(); + TextPosition indented = startOfContent( getSelectionIndex( i ).start() ); + setSelection( i, indented.column() == start.column() ? TextPosition( start.line(), 0 ) + : indented ); + } + mergeSelection(); } void TextDocument::selectToStartOfContent() { - TextPosition start = getSelection().start(); - TextPosition indented = startOfContent( getSelection().start() ); - setSelection( - { indented.column() == start.column() ? TextPosition( start.line(), 0 ) : indented, - getSelection().end() } ); + for ( size_t i = 0; i < mSelection.size(); ++i ) { + TextPosition start = getSelectionIndex( i ).start(); + TextPosition indented = startOfContent( getSelectionIndex( i ).start() ); + setSelection( + i, { indented.column() == start.column() ? TextPosition( start.line(), 0 ) : indented, + getSelectionIndex( i ).end() } ); + } + mergeSelection(); } void TextDocument::moveToStartOfLine() { - setSelection( startOfLine( getSelection().start() ) ); + for ( size_t i = 0; i < mSelection.size(); ++i ) + setSelection( i, startOfLine( getSelectionIndex( i ).start() ) ); + mergeSelection(); } void TextDocument::moveToEndOfLine() { - setSelection( endOfLine( getSelection().start() ) ); + for ( size_t i = 0; i < mSelection.size(); ++i ) + setSelection( i, endOfLine( getSelectionIndex( i ).start() ) ); + mergeSelection(); } void TextDocument::deleteToPreviousChar() { @@ -1275,54 +1299,86 @@ void TextDocument::deleteCurrentLine() { } void TextDocument::selectToPreviousChar() { - selectTo( -1 ); + for ( size_t i = 0; i < mSelection.size(); ++i ) + selectTo( i, -1 ); + mergeSelection(); } void TextDocument::selectToNextChar() { - selectTo( 1 ); + for ( size_t i = 0; i < mSelection.size(); ++i ) + selectTo( i, 1 ); + mergeSelection(); } void TextDocument::selectToPreviousWord() { - setSelection( { previousWordBoundary( getSelection().start() ), getSelection().end() } ); + for ( size_t i = 0; i < mSelection.size(); ++i ) { + setSelection( i, { previousWordBoundary( getSelectionIndex( i ).start() ), + getSelectionIndex( i ).end() } ); + } + mergeSelection(); } void TextDocument::selectToNextWord() { - setSelection( { nextWordBoundary( getSelection().start() ), getSelection().end() } ); + for ( size_t i = 0; i < mSelection.size(); ++i ) { + setSelection( i, { nextWordBoundary( getSelectionIndex( i ).start() ), + getSelectionIndex( i ).end() } ); + } + mergeSelection(); } void TextDocument::selectWord() { - setSelection( { nextWordBoundary( getSelection().start() ), - previousWordBoundary( getSelection().start() ) } ); -} -void TextDocument::selectLine() { - if ( getSelection().start().line() + 1 < (Int64)linesCount() ) { - setSelection( - { { getSelection().start().line() + 1, 0 }, { getSelection().start().line(), 0 } } ); + if ( !hasSelection() ) { + setSelection( { nextWordBoundary( getSelection().start(), false ), + previousWordBoundary( getSelection().start(), false ) } ); } else { - setSelection( { { getSelection().start().line(), - (Int64)line( getSelection().start().line() ).size() }, - { getSelection().start().line(), 0 } } ); + String text( getSelectedText() ); + TextRange res( find( text, getBottomMostCursor().normalized().end() ) ); + if ( res.isValid() ) + addSelection( res.reversed() ); } } +void TextDocument::selectLine() { + for ( size_t i = 0; i < mSelection.size(); ++i ) { + auto sel = getSelectionIndex( i ); + if ( sel.start().line() + 1 < (Int64)linesCount() ) { + setSelection( i, { { sel.start().line() + 1, 0 }, { sel.start().line(), 0 } } ); + } else { + setSelection( i, { { sel.start().line(), (Int64)line( sel.start().line() ).size() }, + { sel.start().line(), 0 } } ); + } + } + mergeSelection(); +} + void TextDocument::selectToPreviousLine() { - TextPosition pos = getSelection().start(); - pos.setLine( pos.line() - 1 ); - setSelection( TextRange( pos, getSelection().end() ) ); + for ( size_t i = 0; i < mSelection.size(); ++i ) { + TextPosition pos = getSelectionIndex( i ).start(); + pos.setLine( pos.line() - 1 ); + setSelection( i, TextRange( pos, getSelectionIndex( i ).end() ) ); + } + mergeSelection(); } void TextDocument::selectToNextLine() { - TextPosition pos = getSelection().start(); - pos.setLine( pos.line() + 1 ); - setSelection( TextRange( pos, getSelection().end() ) ); + for ( size_t i = 0; i < mSelection.size(); ++i ) { + TextPosition pos = getSelectionIndex( i ).start(); + pos.setLine( pos.line() + 1 ); + setSelection( i, TextRange( pos, getSelectionIndex( i ).end() ) ); + } + mergeSelection(); } void TextDocument::selectToStartOfLine() { - selectTo( startOfLine( getSelection().start() ) ); + for ( size_t i = 0; i < mSelection.size(); ++i ) + selectTo( i, startOfLine( getSelectionIndex( i ).start() ) ); + mergeSelection(); } void TextDocument::selectToEndOfLine() { - selectTo( endOfLine( getSelection().start() ) ); + for ( size_t i = 0; i < mSelection.size(); ++i ) + selectTo( i, endOfLine( getSelectionIndex( i ).start() ) ); + mergeSelection(); } void TextDocument::selectToStartOfDoc() { diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index c156b8a35..7155df234 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -266,6 +266,10 @@ void UICodeEditor::draw() { mColorScheme.getEditorSyntaxStyle( "selection_region" ).color ); } + if ( mHighlightSelectionMatch && mDoc->hasSelection() && mDoc->getSelection().inSameLine() ) { + drawSelectionMatch( lineRange, startScroll, lineHeight ); + } + if ( mDoc->hasSelection() ) { auto selections = mDoc->getSelectionsSorted(); for ( const auto& sel : selections ) { @@ -274,10 +278,6 @@ void UICodeEditor::draw() { } } - if ( mHighlightSelectionMatch && mDoc->hasSelection() && mDoc->getSelection().inSameLine() ) { - drawSelectionMatch( lineRange, startScroll, lineHeight ); - } - if ( !mHighlightWord.empty() ) { drawWordMatch( mHighlightWord, lineRange, startScroll, lineHeight ); } diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index e1e29d98d..5f3f180a0 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -2652,6 +2652,11 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe mUISceneNode->getUIIconThemeManager()->setCurrentTheme( iconTheme ); + Clock defClock; + SyntaxDefinitionManager::createSingleton(); + Log::info( "Syntax definitions loaded in %.2f ms.", + defClock.getElapsed().asMilliseconds() ); + UIWidgetCreator::registerWidget( "searchbar", UISearchBar::New ); UIWidgetCreator::registerWidget( "locatebar", UILocateBar::New ); UIWidgetCreator::registerWidget( "globalsearchbar", UIGlobalSearchBar::New );