diff --git a/include/eepp/ui/doc/foldrangeservice.hpp b/include/eepp/ui/doc/foldrangeservice.hpp index 01377b02a..425c38a61 100644 --- a/include/eepp/ui/doc/foldrangeservice.hpp +++ b/include/eepp/ui/doc/foldrangeservice.hpp @@ -16,10 +16,12 @@ class TextDocument; class EE_API FoldRangeServive { public: - using FoldRangeProvider = std::function; + using FoldRangeProvider = std::function; FoldRangeServive( TextDocument* doc ); + bool canFold() const; + void findRegions(); void clear(); diff --git a/include/eepp/ui/doc/textdocument.hpp b/include/eepp/ui/doc/textdocument.hpp index a1363b0ae..e78d9d913 100644 --- a/include/eepp/ui/doc/textdocument.hpp +++ b/include/eepp/ui/doc/textdocument.hpp @@ -100,6 +100,7 @@ class EE_API TextDocument { virtual void onDocumentLineMove( const Int64& /*fromLine*/, const Int64& /*toLine*/, const Int64& /*numLines*/ ) {} virtual TextRange getVisibleRange() const { return {}; }; + virtual void onFoldRegionsUpdated( size_t /*oldCount*/, size_t /*newCount*/ ) {} }; typedef std::function DocumentCommand; @@ -626,6 +627,7 @@ class EE_API TextDocument { protected: friend class TextUndoStack; + friend class FoldRangeServive; Uint64 mModificationId{ 0 }; TextUndoStack mUndoStack; @@ -715,6 +717,8 @@ class EE_API TextDocument { void notifyInterstingCursorChange( TextPosition selection ); + void notifyFoldRegionsUpdated( size_t oldCount, size_t newCount ); + void insertAtStartOfSelectedLines( const String& text, bool skipEmpty ); void removeFromStartOfSelectedLines( const String& text, bool skipEmpty, diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index f982afcba..ecb413d57 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -951,6 +951,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { virtual void onDocumentChanged(); + virtual void onFoldRegionsUpdated( size_t oldCount, size_t newCount ); + virtual Uint32 onMessage( const NodeMessage* msg ); void checkMouseOverColor( const Vector2i& position ); diff --git a/src/eepp/core/debug.cpp b/src/eepp/core/debug.cpp index 00dd5f5a6..797ea0d7c 100644 --- a/src/eepp/core/debug.cpp +++ b/src/eepp/core/debug.cpp @@ -41,7 +41,6 @@ void eeREPORT_ASSERT( const char* File, int Line, const char* Exp ) { #endif #endif - } #ifndef EE_SILENT diff --git a/src/eepp/ui/doc/documentview.cpp b/src/eepp/ui/doc/documentview.cpp index b20303bc2..92eba40b3 100644 --- a/src/eepp/ui/doc/documentview.cpp +++ b/src/eepp/ui/doc/documentview.cpp @@ -384,6 +384,12 @@ bool DocumentView::isLineVisible( Int64 docIdx ) const { void DocumentView::updateCache( Int64 fromLine, Int64 toLine, Int64 numLines ) { if ( isOneToOne() ) return; + + // Unfold ANY modification over a folded range + if ( isFolded( fromLine ) ) { + unfoldRegion( fromLine ); + } + // Get affected visible range Int64 oldIdxFrom = static_cast( toVisibleIndex( fromLine, false ) ); Int64 oldIdxTo = static_cast( toVisibleIndex( toLine, true ) ); @@ -553,6 +559,9 @@ void DocumentView::shiftFoldingRegions( Int64 fromLine, Int64 numLines ) { void DocumentView::verifyStructuralConsistency() { #ifdef EE_DEBUG + if ( isOneToOne() ) + return; + auto visibleLines = mVisibleLines; auto docLineToVisibleIndex = mDocLineToVisibleIndex; auto visibleLinesOffset = mVisibleLinesOffset; diff --git a/src/eepp/ui/doc/foldrangeservice.cpp b/src/eepp/ui/doc/foldrangeservice.cpp index 9c141ad1d..2317dd4cf 100644 --- a/src/eepp/ui/doc/foldrangeservice.cpp +++ b/src/eepp/ui/doc/foldrangeservice.cpp @@ -5,11 +5,18 @@ namespace EE { namespace UI { namespace Doc { FoldRangeServive::FoldRangeServive( TextDocument* doc ) : mDoc( doc ) {} +bool FoldRangeServive::canFold() const { + if ( mProvider && mProvider( mDoc, false ) ) + return true; + // return mDoc->getSyntaxDefinition().getFoldRangeType() != FoldRangeType::Undefined; + return false; +} + void FoldRangeServive::findRegions() { if ( mDoc == nullptr ) return; - if ( mProvider && mProvider( mDoc ) ) + if ( mProvider && mProvider( mDoc, true ) ) return; switch ( mDoc->getSyntaxDefinition().getFoldRangeType() ) { @@ -68,13 +75,19 @@ void FoldRangeServive::shiftFoldingRegions( Int64 fromLine, Int64 numLines ) { } void FoldRangeServive::setFoldingRegions( std::vector regions ) { + size_t newCount = regions.size(); + size_t oldCount; Lock l( mMutex ); - mFoldingRegions.clear(); - std::sort( regions.begin(), regions.end() ); - for ( auto& range : regions ) { - auto line = range.start().line(); - mFoldingRegions[line] = std::move( range ); + { + oldCount = mFoldingRegions.size(); + mFoldingRegions.clear(); + std::sort( regions.begin(), regions.end() ); + for ( auto& range : regions ) { + auto line = range.start().line(); + mFoldingRegions[line] = std::move( range ); + } } + mDoc->notifyFoldRegionsUpdated( oldCount, newCount ); } const FoldRangeServive::FoldRangeProvider& FoldRangeServive::getProvider() const { diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index bd38b8c2d..d75ab67d9 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -3251,6 +3251,13 @@ void TextDocument::notifyInterstingCursorChange( TextPosition selection ) { } } +void TextDocument::notifyFoldRegionsUpdated( size_t oldCount, size_t newCount ) { + Lock l( mClientsMutex ); + for ( auto& client : mClients ) { + client->onFoldRegionsUpdated( oldCount, newCount ); + } +} + void TextDocument::notifySelectionChanged( TextRange selection ) { if ( !selection.isValid() ) selection = getSelection(); diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index ebb840b62..eb1d6cff7 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -649,6 +649,15 @@ void UICodeEditor::onDocumentChanged() { sendEvent( &event ); } +void UICodeEditor::onFoldRegionsUpdated( size_t oldCount, size_t newCount ) { + if ( oldCount == 0 && newCount > 0 ) { + runOnMainThread( [this] { + invalidateLineWrapMaxWidth( false ); + invalidateLongestLineWidth(); + } ); + } +} + Uint32 UICodeEditor::onMessage( const NodeMessage* msg ) { if ( msg->getMsg() == NodeMessage::MouseDown ) return 1; @@ -658,6 +667,7 @@ Uint32 UICodeEditor::onMessage( const NodeMessage* msg ) { void UICodeEditor::disableEditorFeatures() { mShowLineNumber = false; mShowWhitespaces = false; + mShowFoldingRegion = false; mHighlightCurrentLine = false; mHighlightMatchingBracket = false; mHighlightSelectionMatch = false; @@ -803,7 +813,7 @@ Float UICodeEditor::getLineNumberWidth() const { Float UICodeEditor::getInternalGutterWidth() const { return getLineNumberWidth() + - ( !mShowFoldingRegion || mDoc->getFoldRangeService().empty() ? 0.f : mFoldRegionWidth ); + ( mShowFoldingRegion && mDoc->getFoldRangeService().canFold() ? mFoldRegionWidth : 0.f ); } Float UICodeEditor::getGutterWidth() const { @@ -1459,11 +1469,13 @@ Uint32 UICodeEditor::onMouseMove( const Vector2i& position, const Uint32& flags checkMouseOverLink( position ); } - Vector2f localPos( convertToNodeSpace( position.asFloat() ) ); - bool oldFoldVisible = mFoldsVisible; - mFoldsVisible = localPos.x <= mPaddingPx.Left + getGutterWidth(); - if ( oldFoldVisible != mFoldsVisible ) - invalidateDraw(); + if ( mShowFoldingRegion ) { + Vector2f localPos( convertToNodeSpace( position.asFloat() ) ); + bool oldFoldVisible = mFoldsVisible; + mFoldsVisible = localPos.x <= mPaddingPx.Left + getGutterWidth(); + if ( oldFoldVisible != mFoldsVisible ) + invalidateDraw(); + } return UIWidget::onMouseMove( position, flags ); } @@ -2249,7 +2261,8 @@ template Float UICodeEditor::getTextWidth( const StringTyp } Float glyphWidth = getGlyphWidth(); - size_t len = line.length(); + size_t len = + line.length() ? ( line[line.length() - 1] == '\n' ? line.length() - 1 : line.length() ) : 0; Float x = 0; for ( size_t i = 0; i < len; i++ ) x += ( line[i] == '\t' ) ? glyphWidth * mTabWidth : glyphWidth; @@ -3735,7 +3748,7 @@ void UICodeEditor::drawLineNumbers( const DocumentLineRange& lineRange, const Ve Float w = 0.f; if ( mShowLineNumber ) w += lineNumberWidth; - if ( mShowFoldingRegion && !mDoc->getFoldRangeService().empty() ) + if ( mShowFoldingRegion && mDoc->getFoldRangeService().canFold() ) w += mFoldRegionWidth; primitives.drawRectangle( Rectf( screenStart, Sizef( w, mSize.getHeight() ) ) ); TextRange selection = mDoc->getSelection( true ); @@ -3821,7 +3834,7 @@ void UICodeEditor::drawWhitespaces( const DocumentLineRange& lineRange, const Ve continue; const auto& text = mDoc->line( index ).getText(); - if ( mDocView.isWrappedLine( index ) ) { + if ( mDocView.isWrappedLine( index ) || !mFont->isMonospace() ) { for ( size_t i = 0; i < text.size(); i++ ) { if ( ' ' == text[i] ) { auto offset = @@ -4554,8 +4567,8 @@ void UICodeEditor::setShowFoldingRegion( bool showFoldingRegion ) { } bool UICodeEditor::isMinimapFileTooLarge() const { - return mDoc->linesCount() > 1 && - mDoc->linesCount() > + return mDocView.getVisibleLinesCount() > 1 && + mDocView.getVisibleLinesCount() > eefloor( getMinimapRect( getScreenStart() ).getHeight() / getMinimapLineSpacing() ); } diff --git a/src/tools/ecode/plugins/lsp/lspdocumentclient.cpp b/src/tools/ecode/plugins/lsp/lspdocumentclient.cpp index a6ed1caec..f4e56c81d 100644 --- a/src/tools/ecode/plugins/lsp/lspdocumentclient.cpp +++ b/src/tools/ecode/plugins/lsp/lspdocumentclient.cpp @@ -19,9 +19,9 @@ LSPDocumentClient::LSPDocumentClient( LSPClientServer* server, TextDocument* doc requestSymbolsDelayed(); requestSemanticHighlightingDelayed(); requestFoldRangeDelayed(); - doc->getFoldRangeService().setProvider( [this]( auto ) -> bool { + doc->getFoldRangeService().setProvider( [this]( auto, bool requestFolds ) -> bool { bool ret = mServer->getCapabilities().foldingRangeProvider; - if ( ret ) + if ( ret && requestFolds ) requestFoldRangeDelayed(); return ret; } );