From 86e840170af3fc04d45016096276d72296002bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 12 May 2024 02:58:51 -0300 Subject: [PATCH] Line wrap WIP. --- include/eepp/ui/linewrapping.hpp | 24 ++++- include/eepp/ui/uicodeeditor.hpp | 16 ++-- projects/linux/ee.files | 2 + src/eepp/ui/linewrapping.cpp | 58 ++++++++++-- src/eepp/ui/uicodeeditor.cpp | 150 +++++++++++++++++++++++++------ 5 files changed, 208 insertions(+), 42 deletions(-) diff --git a/include/eepp/ui/linewrapping.hpp b/include/eepp/ui/linewrapping.hpp index a5ef66fc6..427da078d 100644 --- a/include/eepp/ui/linewrapping.hpp +++ b/include/eepp/ui/linewrapping.hpp @@ -32,6 +32,12 @@ class EE_API LineWrapping { bool operator!=( const Config& other ) { return !( *this == other ); } }; + struct VisualLine { + Int64 visualLineIndex; + std::vector visualLines; + Float offset{ 0 }; + }; + static LineWrapInfo computeLineBreaks( const String& string, const FontStyleConfig& fontStyle, Float maxWidth, LineWrapMode mode, bool keepIndentation, Uint32 tabWidth = 4 ); @@ -43,6 +49,8 @@ class EE_API LineWrapping { LineWrapping( std::shared_ptr doc, FontStyleConfig fontStyle, Config config ); + bool isWrapEnabled() const; + size_t getTotalLines() const; const Config& config() const { return mConfig; } @@ -51,12 +59,26 @@ class EE_API LineWrapping { void updateBreaks( Int64 fromLine, Int64 toLine, Int64 numLines ); + Config getConfig() const { return mConfig; } + void setConfig( Config config ); void setMaxWidth( Float maxWidth ); void setFontStyle( FontStyleConfig fontStyle ); + void setLineWrapMode( LineWrapMode mode ); + + TextPosition getDocumentLine( Int64 visibleIndex ) const; + + Float getLineOffset( Int64 docIdx ) const; + + Int64 toWrappedIndex( Int64 docIdx, bool retLast = false ) const; + + bool isWrappedLine( Int64 docIdx ) const; + + VisualLine getVisualLine( Int64 docIdx ) const; + protected: std::shared_ptr mDoc; FontStyleConfig mFontStyle; @@ -65,8 +87,6 @@ class EE_API LineWrapping { std::vector mWrappedLines; std::vector mWrappedLinesOffset; std::vector mWrappedLineToIndex; - - Int64 toWrappedIndex( Int64 docIdx, bool retLast ); }; }} // namespace EE::UI diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index a1661f154..65eb05988 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -72,23 +73,23 @@ class UICodeEditorPlugin { return false; } virtual void drawBeforeLineText( UICodeEditor*, const Int64&, Vector2f, const Float&, - const Float& ){}; + const Float& ) {}; virtual void drawAfterLineText( UICodeEditor* /*editor*/, const Int64& /*index*/, Vector2f /*position*/, const Float& /*fontSize*/, - const Float& /*lineHeight*/ ){}; + const Float& /*lineHeight*/ ) {}; virtual void minimapDrawBeforeLineText( UICodeEditor* /*editor*/, const Int64& /*index*/, const Vector2f& /*position*/, const Vector2f& /*size*/, const Float& /*charWidth*/, - const Float& /*gutterWidth*/ ){}; + const Float& /*gutterWidth*/ ) {}; virtual void minimapDrawAfterLineText( UICodeEditor*, const Int64&, const Vector2f&, - const Vector2f&, const Float&, const Float& ){}; + const Vector2f&, const Float&, const Float& ) {}; virtual void drawGutter( UICodeEditor* /*editor*/, const Int64& /*index*/, const Vector2f& /*screenStart*/, const Float& /*lineHeight*/, - const Float& /*gutterWidth*/, const Float& /*fontSize*/ ){}; + const Float& /*gutterWidth*/, const Float& /*fontSize*/ ) {}; virtual void drawTop( UICodeEditor* /*editor*/, const Vector2f& /*screenStart*/, - const Sizef& /*size*/, const Float& /*fontSize*/ ){}; + const Sizef& /*size*/, const Float& /*fontSize*/ ) {}; Uint32 addOnReadyCallback( const OnReadyCb& cb ) { mOnReadyCallbacks[mReadyCbNum++] = cb; @@ -647,6 +648,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { Font* mFont; UIFontStyleConfig mFontStyleConfig; std::shared_ptr mDoc; + LineWrapping mLineWrapping; Clock mBlinkTimer; Time mBlinkTime; bool mDirtyEditor{ false }; @@ -939,6 +941,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void updateIMELocation(); void drawLockedIcon( const Vector2f start ); + + size_t getTotalVisibleLines() const; }; }} // namespace EE::UI diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 78771cc75..9a6d918f3 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -302,6 +302,7 @@ ../../include/eepp/thirdparty/chipmunk/cpSpace.h ../../include/eepp/thirdparty/chipmunk/cpSpatialIndex.h ../../include/eepp/thirdparty/chipmunk/cpVect.h +../../include/eepp/ui/linewrapping.hpp ../../include/eepp/ui/models/model.hpp ../../include/eepp/ui/abstract/uiabstracttableview.hpp ../../include/eepp/ui/abstract/uiabstractview.hpp @@ -1117,6 +1118,7 @@ ../../src/eepp/ui/doc/textformat.cpp ../../src/eepp/ui/doc/textundostack.cpp ../../src/eepp/ui/keyboardshortcut.cpp +../../src/eepp/ui/linewrapping.cpp ../../src/eepp/ui/models/filesystemmodel.cpp ../../src/eepp/ui/models/model.cpp ../../src/eepp/ui/models/modelindex.cpp diff --git a/src/eepp/ui/linewrapping.cpp b/src/eepp/ui/linewrapping.cpp index a4ac38017..9e423b4f6 100644 --- a/src/eepp/ui/linewrapping.cpp +++ b/src/eepp/ui/linewrapping.cpp @@ -176,6 +176,10 @@ LineWrapping::LineWrapping( std::shared_ptr doc, FontStyleConfig f mFontStyle( std::move( fontStyle ) ), mConfig( std::move( config ) ) {} +bool LineWrapping::isWrapEnabled() const { + return mConfig.mode != LineWrapMode::NoWrap; +} + void LineWrapping::setMaxWidth( Float maxWidth ) { if ( maxWidth != mMaxWidth ) { mMaxWidth = maxWidth; @@ -190,6 +194,25 @@ void LineWrapping::setFontStyle( FontStyleConfig fontStyle ) { } } +void LineWrapping::setLineWrapMode( LineWrapMode mode ) { + if ( mode != mConfig.mode ) { + mConfig.mode = mode; + reconstructBreaks(); + } +} + +TextPosition LineWrapping::getDocumentLine( Int64 visibleIndex ) const { + if ( mConfig.mode == LineWrapMode::NoWrap ) + return { visibleIndex, 0 }; + return mWrappedLines[eeclamp( visibleIndex, 0ll, + static_cast( mWrappedLines.size() - 1 ) )]; +} + +Float LineWrapping::getLineOffset( Int64 docIdx ) const { + return mWrappedLinesOffset[eeclamp( docIdx, 0ll, + static_cast( mWrappedLinesOffset.size() - 1 ) )]; +} + void LineWrapping::setConfig( Config config ) { if ( config != mConfig ) { mConfig = std::move( config ); @@ -205,8 +228,11 @@ void LineWrapping::reconstructBreaks() { mWrappedLineToIndex.clear(); mWrappedLinesOffset.clear(); + if ( mConfig.mode == LineWrapMode::NoWrap ) + return; + Int64 linesCount = mDoc->linesCount(); - mWrappedLines.reserve( linesCount * 2 ); + mWrappedLines.reserve( linesCount ); mWrappedLinesOffset.reserve( linesCount ); for ( auto i = 0; i < linesCount; i++ ) { @@ -230,13 +256,11 @@ void LineWrapping::reconstructBreaks() { } } -Int64 LineWrapping::toWrappedIndex( Int64 docIdx, bool retLast ) { - auto idx = - mWrappedLineToIndex[docIdx < 0 - ? 0 - : ( docIdx >= static_cast( mWrappedLineToIndex.size() ) - ? mWrappedLineToIndex.size() - 1 - : docIdx )]; +Int64 LineWrapping::toWrappedIndex( Int64 docIdx, bool retLast ) const { + if ( mConfig.mode == LineWrapMode::NoWrap ) + return docIdx; + auto idx = mWrappedLineToIndex[eeclamp( docIdx, 0ll, + static_cast( mWrappedLineToIndex.size() - 1 ) )]; if ( retLast ) { Int64 lastOfLine = mWrappedLines[idx].line(); Int64 wrappedCount = mWrappedLines.size(); @@ -250,7 +274,25 @@ Int64 LineWrapping::toWrappedIndex( Int64 docIdx, bool retLast ) { return idx; } +bool LineWrapping::isWrappedLine( Int64 docIdx ) const { + return isWrapEnabled() && toWrappedIndex( docIdx ) != toWrappedIndex( docIdx, true ); +} + +LineWrapping::VisualLine LineWrapping::getVisualLine( Int64 docIdx ) const { + VisualLine line; + Int64 fromIdx = toWrappedIndex( docIdx ); + Int64 toIdx = toWrappedIndex( docIdx, true ); + line.visualLineIndex = fromIdx; + line.visualLines.reserve( toIdx - fromIdx + 1 ); + for ( Int64 i = fromIdx; i <= toIdx; i++ ) + line.visualLines.emplace_back( mWrappedLines[i] ); + line.offset = mWrappedLinesOffset[docIdx]; + return line; +} + void LineWrapping::updateBreaks( Int64 fromLine, Int64 toLine, Int64 numLines ) { + if ( mConfig.mode == LineWrapMode::NoWrap ) + return; // Get affected wrapped range Int64 oldIdxFrom = toWrappedIndex( fromLine, false ); Int64 oldIdxTo = toWrappedIndex( toLine, true ); diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 45251cf27..ac2217cd1 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -119,6 +119,7 @@ UICodeEditor::UICodeEditor( const std::string& elementTag, const bool& autoRegis UIWidget( elementTag ), mFont( FontManager::instance()->getByName( "monospace" ) ), mDoc( std::make_shared() ), + mLineWrapping( mDoc, mFontStyleConfig, {} ), mBlinkTime( Seconds( 0.5f ) ), mTabWidth( 4 ), mMouseWheelScroll( 50 ), @@ -160,6 +161,8 @@ UICodeEditor::UICodeEditor( const std::string& elementTag, const bool& autoRegis mDoc->registerClient( this ); subscribeScheduledUpdate(); + mLineWrapping.setLineWrapMode( LineWrapMode::Word ); + if ( autoRegisterBaseCommands ) registerCommands(); if ( autoRegisterBaseKeybindings ) @@ -267,10 +270,11 @@ void UICodeEditor::draw() { if ( !mLocked && mHighlightCurrentLine ) { for ( const auto& sel : mDoc->getSelections() ) { primitives.setColor( Color( mCurrentLineBackgroundColor ).blendAlpha( mAlpha ) ); - primitives.drawRectangle( - Rectf( Vector2f( startScroll.x + mScroll.x, - startScroll.y + sel.start().line() * lineHeight ), - Sizef( mSize.getWidth(), lineHeight ) ) ); + primitives.drawRectangle( Rectf( + Vector2f( startScroll.x + mScroll.x, + startScroll.y + + mLineWrapping.toWrappedIndex( sel.start().line() ) * lineHeight ), + Sizef( mSize.getWidth(), lineHeight ) ) ); } } @@ -324,7 +328,9 @@ void UICodeEditor::draw() { for ( unsigned long i = lineRange.first; i <= lineRange.second; i++ ) { Vector2f curScroll( - { startScroll.x, static_cast( startScroll.y + lineHeight * (double)i ) } ); + { startScroll.x, + static_cast( startScroll.y + + lineHeight * (double)mLineWrapping.toWrappedIndex( i ) ) } ); for ( auto& plugin : mPlugins ) plugin->drawBeforeLineText( this, i, curScroll, charSize, lineHeight ); @@ -349,7 +355,9 @@ void UICodeEditor::draw() { if ( hasFocus() && getUISceneNode()->getWindow()->getIME().isEditing() ) { Vector2f cursorPos( startScroll.x + getXOffsetCol( cursor ), - startScroll.y + cursor.line() * lineHeight + getLineOffset() ); + startScroll.y + + mLineWrapping.toWrappedIndex( cursor.line() ) * lineHeight + + getLineOffset() ); FontStyleConfig config( mFontStyleConfig ); config.FontColor = mFontStyleConfig.getFontSelectedColor(); getUISceneNode()->getWindow()->getIME().draw( cursorPos, getFontHeight(), config, @@ -572,11 +580,15 @@ UICodeEditor* UICodeEditor::setFont( Font* font ) { void UICodeEditor::onFontChanged() { invalidateLinesCache(); udpateGlyphWidth(); + mLineWrapping.setFontStyle( mFontStyleConfig ); + invalidateDraw(); } void UICodeEditor::onFontStyleChanged() { invalidateLinesCache(); udpateGlyphWidth(); + mLineWrapping.setFontStyle( mFontStyleConfig ); + invalidateDraw(); } void UICodeEditor::onDocumentLoaded( TextDocument* ) {} @@ -586,6 +598,7 @@ void UICodeEditor::onDocumentReloaded( TextDocument* ) { sendEvent( &event ); invalidateDraw(); invalidateLongestLineWidth(); + mLineWrapping.reconstructBreaks(); } void UICodeEditor::onDocumentLoaded() { @@ -593,6 +606,7 @@ void UICodeEditor::onDocumentLoaded() { sendEvent( &event ); invalidateDraw(); invalidateLongestLineWidth(); + mLineWrapping.reconstructBreaks(); } void UICodeEditor::onDocumentChanged() { @@ -647,8 +661,6 @@ UICodeEditor* UICodeEditor::setFontSize( const Float& size ) { mFontStyleConfig.CharacterSize = eeabs( size - (int)size ) == 0.5f || (int)size == size ? size : eefloor( size ); mFontSize = mFontStyleConfig.CharacterSize; - udpateGlyphWidth(); - invalidateDraw(); onFontChanged(); } return this; @@ -702,7 +714,12 @@ const Uint32& UICodeEditor::getTabWidth() const { } UICodeEditor* UICodeEditor::setTabWidth( const Uint32& tabWidth ) { - mTabWidth = tabWidth; + if ( mTabWidth != tabWidth ) { + mTabWidth = tabWidth; + auto config = mLineWrapping.getConfig(); + config.tabWidth = tabWidth; + mLineWrapping.setConfig( config ); + } return this; } @@ -882,7 +899,7 @@ void UICodeEditor::invalidateLongestLineWidth() { mLongestLineWidthLastUpdate.restart(); } -Uint32 UICodeEditor::onFocus( NodeFocusReason reason ) { +Uint32 UICodeEditor::onFocus( NodeFocusReason reason ) { if ( !mLocked ) { mLastExecuteEventId = getUISceneNode()->getWindow()->getInput()->getEventsSentId(); resetCursor(); @@ -970,6 +987,10 @@ void UICodeEditor::drawLockedIcon( const Vector2f start ) { fileLockIcon->setColor( col ); } +size_t UICodeEditor::getTotalVisibleLines() const { + return mLineWrapping.getTotalLines(); +} + Uint32 UICodeEditor::onTextEditing( const TextEditingEvent& event ) { UIWidget::onTextEditing( event ); mLastActivity.restart(); @@ -1051,9 +1072,9 @@ Vector2f UICodeEditor::getViewPortLineCount() const { Sizef UICodeEditor::getMaxScroll() const { Vector2f vplc( getViewPortLineCount() ); return Sizef( eemax( 0.f, mLongestLineWidth - getViewportWidth() ), - vplc.y > mDoc->linesCount() - 1 + vplc.y > getTotalVisibleLines() - 1 ? 0.f - : eefloor( mDoc->linesCount() - getViewPortLineCount().y ) * + : eefloor( getTotalVisibleLines() - getViewPortLineCount().y ) * getLineHeight() ); } @@ -1524,7 +1545,8 @@ Vector2f UICodeEditor::getRelativeScreenPosition( const TextPosition& pos ) { Vector2f startScroll( start - mScroll ); auto lineHeight = getLineHeight(); return { startScroll.x + getXOffsetCol( pos ), - startScroll.y + pos.line() * lineHeight + getLineOffset() }; + startScroll.y + mLineWrapping.toWrappedIndex( pos.line() ) * lineHeight + + getLineOffset() }; } bool UICodeEditor::getShowLinesRelativePosition() const { @@ -1547,7 +1569,9 @@ void UICodeEditor::drawCursor( const Vector2f& startScroll, const Float& lineHei const TextPosition& cursor ) { if ( mCursorVisible && !mLocked && isTextSelectionEnabled() ) { Vector2f cursorPos( startScroll.x + getXOffsetCol( cursor ), - startScroll.y + cursor.line() * lineHeight + getLineOffset() ); + startScroll.y + + mLineWrapping.toWrappedIndex( cursor.line() ) * lineHeight + + getLineOffset() ); Primitives primitives; primitives.setColor( Color( mCaretColor ).blendAlpha( mAlpha ) ); primitives.drawRectangle( @@ -1558,11 +1582,13 @@ void UICodeEditor::drawCursor( const Vector2f& startScroll, const Float& lineHei void UICodeEditor::onSizeChange() { UIWidget::onSizeChange(); invalidateEditor( false ); + mLineWrapping.setMaxWidth( getViewportWidth() ); } void UICodeEditor::onPaddingChange() { UIWidget::onPaddingChange(); invalidateEditor( false ); + mLineWrapping.setMaxWidth( getViewportWidth() ); } std::pair UICodeEditor::findLongestLineInRange( const TextRange& range ) { @@ -1728,6 +1754,8 @@ void UICodeEditor::onDocumentTextChanged( const DocumentContentChange& change ) invalidateDraw(); checkMatchingBrackets(); sendCommonEvent( Event::OnTextChanged ); + mLineWrapping.updateBreaks( change.range.start().line(), change.range.end().line(), + change.range.length() ); if ( !change.text.empty() ) { auto range = findLongestLineInRange( change.range ); @@ -1808,6 +1836,8 @@ void UICodeEditor::onDocumentLineMove( const Int64& fromLine, const Int64& numLi } } } + mLineWrapping.updateBreaks( fromLine, std::min( fromLine + numLines, linesCount - 1 ), + numLines ); } else if ( numLines < 0 ) { for ( Int64 i = fromLine; i < linesCount; i++ ) { auto lineIt = mLinesWidthCache.find( i - numLines ); @@ -1818,6 +1848,7 @@ void UICodeEditor::onDocumentLineMove( const Int64& fromLine, const Int64& numLi mLinesWidthCache[i] = std::move( nl.mapped() ); } } + mLineWrapping.updateBreaks( std::max( 0ll, fromLine + numLines ), fromLine, numLines ); } } @@ -1829,8 +1860,13 @@ void UICodeEditor::onDocumentDirtyOnFileSystem( TextDocument* doc ) { std::pair UICodeEditor::getVisibleLineRange() const { Float lineHeight = getLineHeight(); Float minLine = eemax( 0.f, eefloor( mScroll.y / lineHeight ) ); - Float maxLine = eemin( mDoc->linesCount() - 1.f, + Float maxLine = eemin( getTotalVisibleLines() - 1.f, eefloor( ( mSize.getHeight() + mScroll.y ) / lineHeight ) + 1 ); + if ( mLineWrapping.isWrapEnabled() ) { + return std::make_pair( + (Uint64)mLineWrapping.getDocumentLine( minLine ).line(), + (Uint64)mLineWrapping.getDocumentLine( maxLine ).line() ); + } return std::make_pair( (Uint64)minLine, (Uint64)maxLine ); } @@ -3002,7 +3038,8 @@ void UICodeEditor::drawWordRanges( const TextRanges& ranges, const std::pair& Rectf selRect; Int64 startCol = pos; Int64 endCol = pos + text.size(); - selRect.Top = startScroll.y + ln * lineHeight; + selRect.Top = startScroll.y + mLineWrapping.toWrappedIndex( ln ) * lineHeight; selRect.Bottom = selRect.Top + lineHeight; selRect.Left = startScroll.x + getXOffsetCol( { ln, startCol } ); selRect.Right = startScroll.x + getXOffsetCol( { ln, endCol } ); @@ -3082,6 +3119,60 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo Sizef size; FontStyleConfig fontStyle( mFontStyleConfig ); fontStyle.CharacterSize = fontSize; + bool isWrappedLine = mLineWrapping.isWrappedLine( line ); + + if ( isWrappedLine ) { + auto vline = mLineWrapping.getVisualLine( line ); + size_t curvline = 1; + size_t nextLineCol = vline.visualLines[curvline].column(); + for ( const auto& token : tokens ) { + const SyntaxColorScheme::Style& style = mColorScheme.getSyntaxStyle( token.type ); + fontStyle.Style = style.style; + fontStyle.FontColor = Color( style.color ).blendAlpha( mAlpha ); + fontStyle.OutlineThickness = style.outlineThickness; + if ( fontStyle.OutlineThickness ) + fontStyle.OutlineColor = style.outlineColor; + + while ( pos <= strLine.size() ) { + auto maxLength = nextLineCol - pos; + String::View text = strLine.view().substr( + pos, std::min( static_cast( token.len ), maxLength ) ); + + if ( style.background != Color::Transparent ) { + primitives.setColor( Color( style.background ).blendAlpha( mAlpha ) ); + primitives.drawRectangle( + Rectf( position, Sizef( getTextWidth( text ), lineHeight ) ) ); + } + + position.x += Text::draw( text, { position.x, position.y + lineOffset }, fontStyle, + mTabWidth ) + .getWidth(); + pos += text.size(); + + if ( pos < nextLineCol || maxLength == 0 ) + break; + + position.y += lineHeight; + position.x = originalPosition.x + vline.offset; + curvline++; + // bool nbreak = pos == nextLineCol && nextLineCol - pos == 0; + if ( curvline < vline.visualLines.size() ) { + nextLineCol = vline.visualLines[curvline].column(); + } else { + nextLineCol = strLine.size(); + } + /*if ( nbreak ) + break;*/ + } + } + + if ( mDoc->mightBeBinary() && mFont->getType() == FontType::TTF ) { + FontTrueType* ttf = static_cast( mFont ); + ttf->setEnableFallbackFont( isFallbackFont ); + ttf->setEnableEmojiFallback( isEmojiFallbackFont ); + } + return; + } for ( const auto& token : tokens ) { String::View text = strLine.view(); @@ -3243,7 +3334,7 @@ void UICodeEditor::drawTextRange( const TextRange& range, const std::pairline( ln ).getText(); Rectf selRect; - selRect.Top = startScroll.y + ln * lineHeight; + selRect.Top = startScroll.y + mLineWrapping.toWrappedIndex( ln ) * lineHeight; selRect.Bottom = selRect.Top + lineHeight; if ( range.start().line() == ln ) { selRect.Left = startScroll.x + getXOffsetCol( { ln, range.start().column() } ); @@ -3287,7 +3378,9 @@ void UICodeEditor::drawLineNumbers( const std::pair& lineRange, } Text::draw( pos, Vector2f( screenStart.x + mLineNumberPaddingLeft, - startScroll.y + lineHeight * (double)i + lineOffset ), + startScroll.y + + lineHeight * (double)mLineWrapping.toWrappedIndex( i ) + + lineOffset ), mFontStyleConfig.Font, fontSize, ( i >= selection.start().line() && i <= selection.end().line() ) ? mLineNumberActiveFontColor @@ -3303,10 +3396,13 @@ void UICodeEditor::drawColorPreview( const Vector2f& startScroll, const Float& l primitives.setColor( mPreviewColor ); Float startX = getXOffsetCol( mPreviewColorRange.start() ); Float endX = getXOffsetCol( mPreviewColorRange.end() ); - primitives.drawRectangle( Rectf( - Vector2f( startScroll.x + mScroll.x + startX, - startScroll.y + mPreviewColorRange.start().line() * lineHeight + lineHeight ), - Sizef( endX - startX, lineHeight * 2 ) ) ); + primitives.drawRectangle( + Rectf( Vector2f( startScroll.x + mScroll.x + startX, + startScroll.y + + mLineWrapping.toWrappedIndex( mPreviewColorRange.start().line() ) * + lineHeight + + lineHeight ), + Sizef( endX - startX, lineHeight * 2 ) ) ); } void UICodeEditor::drawWhitespaces( const std::pair& lineRange, @@ -3324,7 +3420,8 @@ void UICodeEditor::drawWhitespaces( const std::pair& lineRange, adv->setColor( color ); cpoint->setColor( color ); for ( int index = lineRange.first; index <= lineRange.second; index++ ) { - Vector2f position( { startScroll.x, startScroll.y + lineHeight * index } ); + Vector2f position( + { startScroll.x, startScroll.y + lineHeight * mLineWrapping.toWrappedIndex( index ) } ); const auto& text = mDoc->line( index ).getText(); for ( size_t i = 0; i < text.size(); i++ ) { if ( position.x + mScroll.x + ( text[i] == '\t' ? tabWidth : glyphW ) >= mScreenPos.x && @@ -3381,7 +3478,8 @@ void UICodeEditor::drawIndentationGuides( const std::pair& lineRange, ? getTabWidth() : mDoc->getIndentWidth(); for ( int index = lineRange.first; index <= lineRange.second; index++ ) { - Vector2f position( { startScroll.x, startScroll.y + lineHeight * index } ); + Vector2f position( + { startScroll.x, startScroll.y + lineHeight * mLineWrapping.toWrappedIndex( index ) } ); int spaces = getLineIndentGuideSpaces( *mDoc.get(), index, indentSize ); for ( int i = 0; i < spaces; i += indentSize ) p.drawRectangle( Rectf( { position.x + spaceW * i, position.y }, { w, lineHeight } ) ); @@ -3400,7 +3498,7 @@ void UICodeEditor::drawLineEndings( const std::pair& lineRange, nl->setColor( color ); for ( int index = lineRange.first; index <= lineRange.second; index++ ) { Vector2f position( { startScroll.x + getLineWidth( index ) - getGlyphWidth(), - startScroll.y + lineHeight * index } ); + startScroll.y + lineHeight * mLineWrapping.toWrappedIndex( index ) } ); nl->draw( Vector2f( position.x, position.y ) ); } }