Line wrap WIP.

This commit is contained in:
Martín Lucas Golini
2024-05-12 02:58:51 -03:00
parent c7ab4109f5
commit 86e840170a
5 changed files with 208 additions and 42 deletions

View File

@@ -32,6 +32,12 @@ class EE_API LineWrapping {
bool operator!=( const Config& other ) { return !( *this == other ); }
};
struct VisualLine {
Int64 visualLineIndex;
std::vector<TextPosition> 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<TextDocument> 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<TextDocument> mDoc;
FontStyleConfig mFontStyle;
@@ -65,8 +87,6 @@ class EE_API LineWrapping {
std::vector<TextPosition> mWrappedLines;
std::vector<Float> mWrappedLinesOffset;
std::vector<Int64> mWrappedLineToIndex;
Int64 toWrappedIndex( Int64 docIdx, bool retLast );
};
}} // namespace EE::UI

View File

@@ -6,6 +6,7 @@
#include <eepp/ui/doc/syntaxhighlighter.hpp>
#include <eepp/ui/doc/textdocument.hpp>
#include <eepp/ui/keyboardshortcut.hpp>
#include <eepp/ui/linewrapping.hpp>
#include <eepp/ui/uifontstyleconfig.hpp>
#include <eepp/ui/uiwidget.hpp>
#include <unordered_map>
@@ -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<Doc::TextDocument> 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

View File

@@ -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

View File

@@ -176,6 +176,10 @@ LineWrapping::LineWrapping( std::shared_ptr<TextDocument> 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<Int64>( mWrappedLines.size() - 1 ) )];
}
Float LineWrapping::getLineOffset( Int64 docIdx ) const {
return mWrappedLinesOffset[eeclamp( docIdx, 0ll,
static_cast<Int64>( 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<Int64>( 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<Int64>( 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 );

View File

@@ -119,6 +119,7 @@ UICodeEditor::UICodeEditor( const std::string& elementTag, const bool& autoRegis
UIWidget( elementTag ),
mFont( FontManager::instance()->getByName( "monospace" ) ),
mDoc( std::make_shared<TextDocument>() ),
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<float>( startScroll.y + lineHeight * (double)i ) } );
{ startScroll.x,
static_cast<float>( 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<size_t, Float> 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<Uint64, Uint64> 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, Uint64>(
(Uint64)mLineWrapping.getDocumentLine( minLine ).line(),
(Uint64)mLineWrapping.getDocumentLine( maxLine ).line() );
}
return std::make_pair<Uint64, Uint64>( (Uint64)minLine, (Uint64)maxLine );
}
@@ -3002,7 +3038,8 @@ void UICodeEditor::drawWordRanges( const TextRanges& ranges, const std::pair<int
Rectf selRect;
Int64 startCol = range.start().column();
Int64 endCol = range.end().column();
selRect.Top = startScroll.y + range.start().line() * lineHeight;
selRect.Top =
startScroll.y + mLineWrapping.toWrappedIndex( range.start().line() ) * lineHeight;
selRect.Bottom = selRect.Top + lineHeight;
selRect.Left = startScroll.x + getXOffsetCol( { range.start().line(), startCol } );
selRect.Right = startScroll.x + getXOffsetCol( { range.start().line(), endCol } );
@@ -3043,7 +3080,7 @@ void UICodeEditor::drawWordMatch( const String& text, const std::pair<int, int>&
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<size_t>( 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<FontTrueType*>( 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::pair<int, i
for ( auto ln = startLine; ln <= endLine; ln++ ) {
const String& line = mDoc->line( 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<int, int>& 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<int, int>& lineRange,
@@ -3324,7 +3420,8 @@ void UICodeEditor::drawWhitespaces( const std::pair<int, int>& 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<int, int>& 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<int, int>& 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 ) );
}
}