From d39be5958d4b2a0bf2181bc1978055855cf5cc43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Thu, 30 May 2024 20:04:03 -0300 Subject: [PATCH] Folding fixes. --- include/eepp/ui/doc/documentview.hpp | 7 +++- src/eepp/ui/doc/documentview.cpp | 53 +++++++++++++++++++++++----- src/eepp/ui/doc/foldrangeservice.cpp | 8 ++--- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/include/eepp/ui/doc/documentview.hpp b/include/eepp/ui/doc/documentview.hpp index 986039672..d9490a6b7 100644 --- a/include/eepp/ui/doc/documentview.hpp +++ b/include/eepp/ui/doc/documentview.hpp @@ -139,6 +139,8 @@ class EE_API DocumentView { bool isOneToOne() const; + std::vector intersectsFoldedRegions( const TextRange& range ) const; + protected: std::shared_ptr mDoc; FontStyleConfig mFontStyle; @@ -151,7 +153,8 @@ class EE_API DocumentView { bool mPendingReconstruction{ false }; bool mUnderConstruction{ false }; - void changeVisibility( Int64 fromDocIdx, Int64 toDocIdx, bool visible ); + void changeVisibility( Int64 fromDocIdx, Int64 toDocIdx, bool visible, + bool recomputeOffset = true ); void removeFoldedRegion( const TextRange& region ); @@ -160,6 +163,8 @@ class EE_API DocumentView { void verifyStructuralConsistency(); void recomputeDocLineToVisibleIndex( Int64 fromVisibleIndex ); + + void unfoldRegion( Int64 foldDocIdx, bool verifyConsistency, bool recomputeOffset = true ); }; }}} // namespace EE::UI::Doc diff --git a/src/eepp/ui/doc/documentview.cpp b/src/eepp/ui/doc/documentview.cpp index 73bd1cfd8..db5770a55 100644 --- a/src/eepp/ui/doc/documentview.cpp +++ b/src/eepp/ui/doc/documentview.cpp @@ -386,13 +386,27 @@ bool DocumentView::isLineVisible( Int64 docIdx ) const { mDocLineToVisibleIndex[docIdx] != static_cast( VisibleIndex::invalid ); } +std::vector DocumentView::intersectsFoldedRegions( const TextRange& range ) const { + std::vector folds; + for ( const auto& fold : mFoldedRegions ) { + if ( fold.intersectsLineRange( range ) ) + folds.push_back( fold ); + } + return folds; +} + void DocumentView::updateCache( Int64 fromLine, Int64 toLine, Int64 numLines ) { if ( isOneToOne() ) return; // Unfold ANY modification over a folded range - if ( isFolded( fromLine ) ) { - unfoldRegion( fromLine ); + if ( numLines < 0 ) { + auto foldedRegions = intersectsFoldedRegions( { { fromLine, 0 }, { toLine, 0 } } ); + for ( const auto& fold : foldedRegions ) + unfoldRegion( fold.start().line(), false, false ); + } else if ( isFolded( fromLine ) ) { + // Offsets will be recomputed here instead in the unfold operation + unfoldRegion( fromLine, false, false ); } // Get affected visible range @@ -480,13 +494,18 @@ void DocumentView::foldRegion( Int64 foldDocIdx ) { } void DocumentView::unfoldRegion( Int64 foldDocIdx ) { + return unfoldRegion( foldDocIdx, true ); +} + +void DocumentView::unfoldRegion( Int64 foldDocIdx, bool verifyConsistency, bool recomputeOffset ) { auto foldRegion = mDoc->getFoldRangeService().find( foldDocIdx ); if ( !foldRegion ) return; Int64 toDocIdx = foldRegion->end().line(); removeFoldedRegion( *foldRegion ); - changeVisibility( foldDocIdx + 1, toDocIdx, true ); - verifyStructuralConsistency(); + changeVisibility( foldDocIdx + 1, toDocIdx, true, recomputeOffset ); + if ( verifyConsistency ) + verifyStructuralConsistency(); if ( isOneToOne() ) clearCache(); } @@ -495,7 +514,8 @@ bool DocumentView::isOneToOne() const { return mConfig.mode == LineWrapMode::NoWrap && mFoldedRegions.empty(); } -void DocumentView::changeVisibility( Int64 fromDocIdx, Int64 toDocIdx, bool visible ) { +void DocumentView::changeVisibility( Int64 fromDocIdx, Int64 toDocIdx, bool visible, + bool recomputeOffset ) { if ( visible ) { auto it = std::lower_bound( mVisibleLines.begin(), mVisibleLines.end(), TextPosition{ fromDocIdx, 0 } ); @@ -503,15 +523,18 @@ void DocumentView::changeVisibility( Int64 fromDocIdx, Int64 toDocIdx, bool visi auto idxOffset = oldIdxFrom; for ( auto i = fromDocIdx; i <= toDocIdx; i++ ) { if ( isFolded( i, true ) ) { - mVisibleLinesOffset[i] = computeOffsets( mDoc->line( i ).getText().view(), - mFontStyle, mConfig.tabWidth ); + if ( recomputeOffset ) { + mVisibleLinesOffset[i] = computeOffsets( mDoc->line( i ).getText().view(), + mFontStyle, mConfig.tabWidth ); + } continue; } auto lb = isWrapEnabled() ? computeLineBreaks( *mDoc, i, mFontStyle, mMaxWidth, mConfig.mode, mConfig.keepIndentation, mConfig.tabWidth ) : LineWrapInfo{ { 0 }, 0 }; - mVisibleLinesOffset[i] = lb.paddingStart; + if ( recomputeOffset ) + mVisibleLinesOffset[i] = lb.paddingStart; for ( const auto& col : lb.wraps ) { mVisibleLines.insert( mVisibleLines.begin() + idxOffset, { i, col } ); idxOffset++; @@ -597,7 +620,19 @@ void DocumentView::verifyStructuralConsistency() { } } - eeASSERT( visibleLinesOffset == mVisibleLinesOffset ); + bool offsetConsistency = visibleLinesOffset == mVisibleLinesOffset; + eeASSERT( offsetConsistency ); + + if ( !offsetConsistency && visibleLinesOffset.size() == mVisibleLinesOffset.size() ) { + for ( size_t i = 0; i < mVisibleLinesOffset.size(); i++ ) { + if ( mVisibleLinesOffset[i] != visibleLinesOffset[i] ) { + eeASSERT( mVisibleLinesOffset[i] == visibleLinesOffset[i] ); + break; + } + } + } + + eeASSERT( mVisibleLinesOffset.size() == mDoc->linesCount() ); #endif } diff --git a/src/eepp/ui/doc/foldrangeservice.cpp b/src/eepp/ui/doc/foldrangeservice.cpp index 3dad79375..3e3ec1804 100644 --- a/src/eepp/ui/doc/foldrangeservice.cpp +++ b/src/eepp/ui/doc/foldrangeservice.cpp @@ -100,8 +100,8 @@ static std::vector findFoldingRangesIndentation( TextDocument* doc ) FoldRangeServive::FoldRangeServive( TextDocument* doc ) : mDoc( doc ) {} bool FoldRangeServive::canFold() const { - // if ( mProvider && mProvider( mDoc, false ) ) - // return true; + if ( mProvider && mProvider( mDoc, false ) ) + return true; auto type = mDoc->getSyntaxDefinition().getFoldRangeType(); return type == FoldRangeType::Braces || type == FoldRangeType::Indentation; } @@ -110,8 +110,8 @@ void FoldRangeServive::findRegions() { if ( mDoc == nullptr || !canFold() ) return; - // if ( mProvider && mProvider( mDoc, true ) ) - // return; + if ( mProvider && mProvider( mDoc, true ) ) + return; switch ( mDoc->getSyntaxDefinition().getFoldRangeType() ) { case FoldRangeType::Braces: