Minor refactor.

This commit is contained in:
Martín Lucas Golini
2024-05-25 00:36:07 -03:00
parent 003a974fa0
commit bca010b606
3 changed files with 73 additions and 88 deletions

View File

@@ -73,7 +73,7 @@ class EE_API DocumentView {
LineWrapMode mode, bool keepIndentation,
Uint32 tabWidth = 4 );
static Float computeOffsets( const String& string, const FontStyleConfig& fontStyle,
static Float computeOffsets( const String::View& string, const FontStyleConfig& fontStyle,
Uint32 tabWidth );
DocumentView( std::shared_ptr<TextDocument> doc, FontStyleConfig fontStyle, Config config );
@@ -134,9 +134,9 @@ class EE_API DocumentView {
FontStyleConfig mFontStyle;
Config mConfig;
Float mMaxWidth{ 0 };
std::vector<TextPosition> mWrappedLines;
std::vector<Float> mWrappedLinesOffset;
std::vector<Int64> mWrappedLineToIndex;
std::vector<TextPosition> mVisibleLines;
std::vector<Float> mVisibleLinesOffset;
std::vector<Int64> mDocLineToVisibleIndex;
bool mPendingReconstruction{ false };
bool mUnderConstruction{ false };
};

View File

@@ -43,12 +43,13 @@ std::string DocumentView::fromLineWrapType( LineWrapType type ) {
}
}
Float DocumentView::computeOffsets( const String& string, const FontStyleConfig& fontStyle,
Float DocumentView::computeOffsets( const String::View& string, const FontStyleConfig& fontStyle,
Uint32 tabWidth ) {
auto nonIndentPos = string.find_first_not_of( " \t\n\v\f\r" );
if ( nonIndentPos != String::InvalidPos )
return Text::getTextWidth( string.view().substr( 0, nonIndentPos ), fontStyle, tabWidth );
static const String sepSpaces = " \t\n\v\f\r";
auto nonIndentPos = string.find_first_not_of( sepSpaces.data() );
if ( nonIndentPos != String::View::npos )
return Text::getTextWidth( string.substr( 0, nonIndentPos ), fontStyle, tabWidth );
return 0.f;
}
@@ -62,13 +63,8 @@ DocumentView::LineWrapInfo DocumentView::computeLineBreaks( const String::View&
if ( string.empty() || nullptr == fontStyle.Font || mode == LineWrapMode::NoWrap )
return info;
if ( keepIndentation ) {
static const String nofOf = " \t\n\v\f\r";
auto nonIndentPos = string.find_first_not_of( nofOf.data() );
if ( nonIndentPos != String::InvalidPos )
info.paddingStart =
Text::getTextWidth( string.substr( 0, nonIndentPos ), fontStyle, tabWidth );
}
if ( keepIndentation )
info.paddingStart = computeOffsets( string, fontStyle, tabWidth );
Float xoffset = 0.f;
Float lastWidth = 0.f;
@@ -177,17 +173,17 @@ void DocumentView::setLineWrapMode( LineWrapMode mode ) {
}
TextPosition DocumentView::getVisibleIndexPosition( VisibleIndex visibleIndex ) const {
if ( mConfig.mode == LineWrapMode::NoWrap || mWrappedLines.empty() )
if ( mConfig.mode == LineWrapMode::NoWrap || mVisibleLines.empty() )
return { static_cast<Int64>( visibleIndex ), 0 };
return mWrappedLines[eeclamp( static_cast<Int64>( visibleIndex ), 0ll,
eemax( static_cast<Int64>( mWrappedLines.size() ) - 1, 0ll ) )];
return mVisibleLines[eeclamp( static_cast<Int64>( visibleIndex ), 0ll,
eemax( static_cast<Int64>( mVisibleLines.size() ) - 1, 0ll ) )];
}
Float DocumentView::getLinePadding( Int64 docIdx ) const {
if ( mConfig.mode == LineWrapMode::NoWrap || mWrappedLinesOffset.empty() )
if ( mConfig.mode == LineWrapMode::NoWrap || mVisibleLinesOffset.empty() )
return 0;
return mWrappedLinesOffset[eeclamp(
docIdx, 0ll, eemax( static_cast<Int64>( mWrappedLinesOffset.size() ) - 1, 0ll ) )];
return mVisibleLinesOffset[eeclamp(
docIdx, 0ll, eemax( static_cast<Int64>( mVisibleLinesOffset.size() ) - 1, 0ll ) )];
}
void DocumentView::setConfig( Config config ) {
@@ -208,32 +204,32 @@ void DocumentView::invalidateCache() {
BoolScopedOp op( mUnderConstruction, true );
mWrappedLines.clear();
mWrappedLineToIndex.clear();
mWrappedLinesOffset.clear();
mVisibleLines.clear();
mDocLineToVisibleIndex.clear();
mVisibleLinesOffset.clear();
if ( mConfig.mode == LineWrapMode::NoWrap )
return;
Int64 linesCount = mDoc->linesCount();
mWrappedLines.reserve( linesCount );
mWrappedLinesOffset.reserve( linesCount );
mVisibleLines.reserve( linesCount );
mVisibleLinesOffset.reserve( linesCount );
for ( auto i = 0; i < linesCount; i++ ) {
auto lb = computeLineBreaks( *mDoc, i, mFontStyle, mMaxWidth, mConfig.mode,
mConfig.keepIndentation, mConfig.tabWidth );
mWrappedLinesOffset.emplace_back( lb.paddingStart );
mVisibleLinesOffset.emplace_back( lb.paddingStart );
for ( const auto& col : lb.wraps )
mWrappedLines.emplace_back( i, col );
mVisibleLines.emplace_back( i, col );
}
std::optional<Int64> lastWrap;
size_t i = 0;
mWrappedLineToIndex.reserve( linesCount );
mDocLineToVisibleIndex.reserve( linesCount );
for ( const auto& wl : mWrappedLines ) {
for ( const auto& wl : mVisibleLines ) {
if ( !lastWrap || *lastWrap != wl.line() ) {
mWrappedLineToIndex.emplace_back( i );
mDocLineToVisibleIndex.emplace_back( i );
lastWrap = wl.line();
}
i++;
@@ -244,15 +240,15 @@ void DocumentView::invalidateCache() {
VisibleIndex DocumentView::toVisibleIndex( Int64 docIdx, bool retLast ) const {
eeASSERT( isLineVisible( docIdx ) );
if ( mConfig.mode == LineWrapMode::NoWrap || mWrappedLineToIndex.empty() )
if ( mConfig.mode == LineWrapMode::NoWrap || mDocLineToVisibleIndex.empty() )
return static_cast<VisibleIndex>( docIdx );
auto idx = mWrappedLineToIndex[eeclamp( docIdx, 0ll,
static_cast<Int64>( mWrappedLineToIndex.size() - 1 ) )];
auto idx = mDocLineToVisibleIndex[eeclamp(
docIdx, 0ll, static_cast<Int64>( mDocLineToVisibleIndex.size() - 1 ) )];
if ( retLast ) {
Int64 lastOfLine = mWrappedLines[idx].line();
Int64 wrappedCount = mWrappedLines.size();
for ( auto i = idx + 1; i < wrappedCount; i++ ) {
if ( mWrappedLines[i].line() == lastOfLine )
Int64 lastOfLine = mVisibleLines[idx].line();
Int64 visibleLinesCount = mVisibleLines.size();
for ( auto i = idx + 1; i < visibleLinesCount; i++ ) {
if ( mVisibleLines[i].line() == lastOfLine )
idx = i;
else
break;
@@ -263,9 +259,9 @@ VisibleIndex DocumentView::toVisibleIndex( Int64 docIdx, bool retLast ) const {
bool DocumentView::isWrappedLine( Int64 docIdx ) const {
if ( isWrapEnabled() && mConfig.mode != LineWrapMode::NoWrap ) {
Int64 wrappedIndex = static_cast<Int64>( toVisibleIndex( docIdx ) );
return wrappedIndex + 1 < static_cast<Int64>( mWrappedLines.size() ) &&
mWrappedLines[wrappedIndex].line() == mWrappedLines[wrappedIndex + 1].line();
Int64 visibleIndex = static_cast<Int64>( toVisibleIndex( docIdx ) );
return visibleIndex + 1 < static_cast<Int64>( mVisibleLines.size() ) &&
mVisibleLines[visibleIndex].line() == mVisibleLines[visibleIndex + 1].line();
}
return false;
}
@@ -282,9 +278,9 @@ DocumentView::VisibleLineInfo DocumentView::getVisibleLineInfo( Int64 docIdx ) c
Int64 toIdx = static_cast<Int64>( toVisibleIndex( docIdx, true ) );
line.visualLines.reserve( toIdx - fromIdx + 1 );
for ( Int64 i = fromIdx; i <= toIdx; i++ )
line.visualLines.emplace_back( mWrappedLines[i] );
line.visualLines.emplace_back( mVisibleLines[i] );
line.visibleIndex = static_cast<VisibleIndex>( fromIdx );
line.paddingStart = mWrappedLinesOffset[docIdx];
line.paddingStart = mVisibleLinesOffset[docIdx];
return line;
}
@@ -300,9 +296,9 @@ DocumentView::VisibleLineRange DocumentView::getVisibleLineRange( const TextPosi
Int64 toIdx = static_cast<Int64>( toVisibleIndex( pos.line(), true ) );
DocumentView::VisibleLineRange info;
for ( Int64 i = fromIdx; i < toIdx; i++ ) {
Int64 fromCol = mWrappedLines[i].column();
Int64 fromCol = mVisibleLines[i].column();
Int64 toCol = i + 1 <= toIdx
? mWrappedLines[i + 1].column() - ( allowVisualLineEnd ? 0 : 1 )
? mVisibleLines[i + 1].column() - ( allowVisualLineEnd ? 0 : 1 )
: mDoc->line( pos.line() ).size();
if ( pos.column() >= fromCol && pos.column() <= toCol ) {
info.visibleIndex = static_cast<VisibleIndex>( i );
@@ -312,7 +308,7 @@ DocumentView::VisibleLineRange DocumentView::getVisibleLineRange( const TextPosi
}
eeASSERT( toIdx >= 0 );
info.visibleIndex = static_cast<VisibleIndex>( toIdx );
info.range = { { pos.line(), mWrappedLines[toIdx].column() },
info.range = { { pos.line(), mVisibleLines[toIdx].column() },
mDoc->endOfLine( { pos.line(), 0ll } ) };
return info;
}
@@ -323,9 +319,9 @@ TextRange DocumentView::getVisibleIndexRange( VisibleIndex visibleIndex ) const
Int64 idx = static_cast<Int64>( visibleIndex );
auto start = getVisibleIndexPosition( visibleIndex );
auto end = start;
if ( idx + 1 < static_cast<Int64>( mWrappedLines.size() ) &&
mWrappedLines[idx + 1].line() == start.line() ) {
end.setColumn( mWrappedLines[idx + 1].column() );
if ( idx + 1 < static_cast<Int64>( mVisibleLines.size() ) &&
mVisibleLines[idx + 1].line() == start.line() ) {
end.setColumn( mVisibleLines[idx + 1].column() );
} else {
end.setColumn( mDoc->line( start.line() ).size() );
}
@@ -352,9 +348,9 @@ void DocumentView::setPendingReconstruction( bool pendingReconstruction ) {
}
void DocumentView::clear() {
mWrappedLines.clear();
mWrappedLineToIndex.clear();
mWrappedLinesOffset.clear();
mVisibleLines.clear();
mDocLineToVisibleIndex.clear();
mVisibleLinesOffset.clear();
}
Float DocumentView::getLineYOffset( VisibleIndex visibleIndex, Float lineHeight ) const {
@@ -372,22 +368,22 @@ bool DocumentView::isLineVisible( Int64 ) const {
void DocumentView::updateCache( Int64 fromLine, Int64 toLine, Int64 numLines ) {
if ( mConfig.mode == LineWrapMode::NoWrap )
return;
// Get affected wrapped range
// Get affected visible range
Int64 oldIdxFrom = static_cast<Int64>( toVisibleIndex( fromLine, false ) );
Int64 oldIdxTo = static_cast<Int64>( toVisibleIndex( toLine, true ) );
// Remove old wrapped lines
mWrappedLines.erase( mWrappedLines.begin() + oldIdxFrom, mWrappedLines.begin() + oldIdxTo + 1 );
// Remove old visible lines
mVisibleLines.erase( mVisibleLines.begin() + oldIdxFrom, mVisibleLines.begin() + oldIdxTo + 1 );
// Remove old offsets
mWrappedLinesOffset.erase( mWrappedLinesOffset.begin() + fromLine,
mWrappedLinesOffset.begin() + toLine + 1 );
mVisibleLinesOffset.erase( mVisibleLinesOffset.begin() + fromLine,
mVisibleLinesOffset.begin() + toLine + 1 );
// Shift the line numbers
if ( numLines != 0 ) {
Int64 wrappedLines = mWrappedLines.size();
for ( Int64 i = oldIdxFrom; i < wrappedLines; i++ )
mWrappedLines[i].setLine( mWrappedLines[i].line() + numLines );
Int64 visibleLinesCount = mVisibleLines.size();
for ( Int64 i = oldIdxFrom; i < visibleLinesCount; i++ )
mVisibleLines[i].setLine( mVisibleLines[i].line() + numLines );
}
// Recompute line breaks
@@ -396,51 +392,40 @@ void DocumentView::updateCache( Int64 fromLine, Int64 toLine, Int64 numLines ) {
for ( auto i = fromLine; i <= netLines; i++ ) {
auto lb = computeLineBreaks( *mDoc, i, mFontStyle, mMaxWidth, mConfig.mode,
mConfig.keepIndentation, mConfig.tabWidth );
mWrappedLinesOffset.insert( mWrappedLinesOffset.begin() + i, lb.paddingStart );
mVisibleLinesOffset.insert( mVisibleLinesOffset.begin() + i, lb.paddingStart );
for ( const auto& col : lb.wraps ) {
mWrappedLines.insert( mWrappedLines.begin() + idxOffset, { i, col } );
mVisibleLines.insert( mVisibleLines.begin() + idxOffset, { i, col } );
idxOffset++;
}
}
// Recompute wrapped line to index
// Recompute document line to visible index
Int64 line = fromLine;
Int64 wrappedLinesCount = mWrappedLines.size();
mWrappedLineToIndex.resize( mDoc->linesCount() );
for ( Int64 wrappedIdx = oldIdxFrom; wrappedIdx < wrappedLinesCount; wrappedIdx++ ) {
if ( mWrappedLines[wrappedIdx].column() == 0 ) {
mWrappedLineToIndex[line] = wrappedIdx;
Int64 visibleLinesCount = mVisibleLines.size();
mDocLineToVisibleIndex.resize( mDoc->linesCount() );
for ( Int64 visibleIdx = oldIdxFrom; visibleIdx < visibleLinesCount; visibleIdx++ ) {
if ( mVisibleLines[visibleIdx].column() == 0 ) {
mDocLineToVisibleIndex[line] = visibleIdx;
line++;
}
}
mWrappedLineToIndex.resize( mDoc->linesCount() );
mDocLineToVisibleIndex.resize( mDoc->linesCount() );
#ifdef EE_DEBUG
if ( mConfig.keepIndentation ) {
auto wrappedOffset = mWrappedLinesOffset;
for ( auto i = fromLine; i <= toLine; i++ ) {
mWrappedLinesOffset[i] =
computeOffsets( mDoc->line( i ).getText(), mFontStyle, mConfig.tabWidth );
}
eeASSERT( wrappedOffset == mWrappedLinesOffset );
}
auto wrappedLines = mWrappedLines;
auto wrappedLinesToIndex = mWrappedLineToIndex;
auto wrappedOffset = mWrappedLinesOffset;
auto visibleLines = mVisibleLines;
auto docLineToVisibleIndex = mDocLineToVisibleIndex;
auto visibleLinesOffset = mVisibleLinesOffset;
invalidateCache();
eeASSERT( wrappedLines == mWrappedLines );
eeASSERT( wrappedLinesToIndex == mWrappedLineToIndex );
eeASSERT( wrappedOffset == mWrappedLinesOffset );
eeASSERT( visibleLines == mVisibleLines );
eeASSERT( docLineToVisibleIndex == mDocLineToVisibleIndex );
eeASSERT( visibleLinesOffset == mVisibleLinesOffset );
#endif
}
size_t DocumentView::getVisibleLinesCount() const {
return mConfig.mode == LineWrapMode::NoWrap ? mDoc->linesCount() : mWrappedLines.size();
return mConfig.mode == LineWrapMode::NoWrap ? mDoc->linesCount() : mVisibleLines.size();
}
}}} // namespace EE::UI::Doc

View File

@@ -1740,7 +1740,7 @@ Float UICodeEditor::getLineWidth( const Int64& docLine ) {
}
void UICodeEditor::updateScrollBar() {
int notVisibleLineCount = (int)mDoc->linesCount() - (int)getViewPortLineCount().y;
Int64 notVisibleLineCount = (Int64)getTotalVisibleLines() - (Int64)getViewPortLineCount().y;
mHScrollBar->setEnabled( false );
mHScrollBar->setVisible( false );