diff --git a/include/eepp/ui/linewrapping.hpp b/include/eepp/ui/doc/documentview.hpp similarity index 90% rename from include/eepp/ui/linewrapping.hpp rename to include/eepp/ui/doc/documentview.hpp index dccb77da9..97339e66d 100644 --- a/include/eepp/ui/linewrapping.hpp +++ b/include/eepp/ui/doc/documentview.hpp @@ -1,5 +1,5 @@ -#ifndef EE_UI_LINEWRAPPING_HPP -#define EE_UI_LINEWRAPPING_HPP +#ifndef EE_UI_DOCUMENTVIEW_HPP +#define EE_UI_DOCUMENTVIEW_HPP #include #include @@ -9,13 +9,13 @@ using namespace EE::Graphics; using namespace EE::UI::Doc; -namespace EE { namespace UI { +namespace EE { namespace UI { namespace Doc { enum class LineWrapMode { NoWrap, Letter, Word }; enum class LineWrapType { Viewport, LineBreakingColumn }; -class EE_API LineWrapping { +class EE_API DocumentView { public: static LineWrapMode toLineWrapMode( std::string mode ); @@ -65,7 +65,7 @@ class EE_API LineWrapping { static Float computeOffsets( const String& string, const FontStyleConfig& fontStyle, Uint32 tabWidth ); - LineWrapping( std::shared_ptr doc, FontStyleConfig fontStyle, Config config ); + DocumentView( std::shared_ptr doc, FontStyleConfig fontStyle, Config config ); bool isWrapEnabled() const; @@ -73,9 +73,9 @@ class EE_API LineWrapping { const Config& config() const { return mConfig; } - void reconstructBreaks(); + void invalidateCache(); - void updateBreaks( Int64 fromLine, Int64 toLine, Int64 numLines ); + void updateCache( Int64 fromLine, Int64 toLine, Int64 numLines ); Config getConfig() const { return mConfig; } @@ -124,6 +124,6 @@ class EE_API LineWrapping { bool mUnderConstruction{ false }; }; -}} // namespace EE::UI +}}} // namespace EE::UI::Doc #endif diff --git a/include/eepp/ui/doc/textrange.hpp b/include/eepp/ui/doc/textrange.hpp index ccc808c48..72bbb9db5 100644 --- a/include/eepp/ui/doc/textrange.hpp +++ b/include/eepp/ui/doc/textrange.hpp @@ -2,6 +2,7 @@ #define EE_UI_DOC_TEXTRANGE_HPP #include +#include #include namespace EE { namespace UI { namespace Doc { @@ -99,6 +100,22 @@ class EE_API TextRange { return true; } + bool intersectsLineRange( const TextRange& range ) const { + eeASSERT( range.isNormalized() ); + return mStart.line() <= static_cast( range.end().line() ) && + static_cast( range.start().line() ) <= mEnd.line(); + } + + template bool intersectsLineRange( T fromLine, T toLine ) const { + return mStart.line() <= static_cast( toLine ) && + static_cast( fromLine ) <= mEnd.line(); + } + + template bool intersectsLineRange( const std::pair& range ) const { + return mStart.line() <= static_cast( range.second ) && + static_cast( range.first ) <= mEnd.line(); + } + bool containsLine( const Int64& line ) const { return line >= mStart.line() && line <= mEnd.line(); } @@ -132,6 +149,8 @@ class EE_API TextRange { return {}; } + bool isNormalized() const { return mStart < mEnd; } + private: TextPosition mStart; TextPosition mEnd; diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index f10fa823c..efa3e657c 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -33,6 +33,12 @@ class UILoader; class UIPopUpMenu; class UIMenuItem; +using DocumentLineRange = std::pair; +using DocumentViewLineRange = std::pair; + +using DrawTextRangesFn = std::function; + class UICodeEditorPlugin { public: typedef std::function OnReadyCb; @@ -72,24 +78,25 @@ class UICodeEditorPlugin { const Vector2i& /*position*/, const Uint32& /*flags*/ ) { return false; } + virtual void drawBeforeLineText( UICodeEditor*, const Int64&, Vector2f, const Float&, const Float& ) {}; + virtual void drawAfterLineText( UICodeEditor* /*editor*/, const Int64& /*index*/, Vector2f /*position*/, const Float& /*fontSize*/, const Float& /*lineHeight*/ ) {}; - virtual void minimapDrawBeforeLineText( - UICodeEditor* /*editor*/, const Int64& /*index*/, const Vector2f& /*linePos*/, - const Vector2f& /*lineSize*/, const Float& /*charWidth*/, const Float& /*gutterWidth*/, - const std::function /* drawTextRanges */ ) {}; + virtual void minimapDrawBefore( UICodeEditor* /*editor*/, const DocumentLineRange&, + const DocumentViewLineRange&, const Vector2f& /*linePos*/, + const Vector2f& /*lineSize*/, const Float& /*charWidth*/, + const Float& /*gutterWidth*/, + const DrawTextRangesFn& /* drawTextRanges */ ) {}; - virtual void minimapDrawAfterLineText( - UICodeEditor* /*editor*/, const Int64& /*lineIdx */, const Vector2f& /* linePos */, - const Vector2f& /* lineSize */, const Float& /* charWidth */, - const Float& /* gutterWidth */, - const std::function /* drawTextRanges */ ) {}; + virtual void minimapDrawAfter( UICodeEditor* /*editor*/, const DocumentLineRange&, + const DocumentViewLineRange&, const Vector2f& /* linePos */, + const Vector2f& /* lineSize */, const Float& /* charWidth */, + const Float& /* gutterWidth */, + const DrawTextRangesFn& /* drawTextRanges */ ) {}; virtual void drawGutter( UICodeEditor* /*editor*/, const Int64& /*index*/, const Vector2f& /*screenStart*/, const Float& /*lineHeight*/, @@ -575,8 +582,6 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { virtual TextRange getVisibleRange() const; - bool isLineVisible( const Uint64& line ) const; - int getVisibleLinesCount() const; const StyleSheetLength& getLineSpacing() const; @@ -675,9 +680,9 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void invalidateLongestLineWidth(); - const LineWrapping& lineWrapping() const { return mLineWrapping; } + const DocumentView& documentView() const { return mDocView; } - LineWrapMode getLineWrapMode() const { return mLineWrapping.getConfig().mode; } + LineWrapMode getLineWrapMode() const { return mDocView.getConfig().mode; } void setLineWrapMode( LineWrapMode mode ); @@ -685,7 +690,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void setLineWrapType( LineWrapType lineWrapType ); - bool getLineWrapKeepIndentation() const { return mLineWrapping.getConfig().keepIndentation; } + bool getLineWrapKeepIndentation() const { return mDocView.getConfig().keepIndentation; } void setLineWrapKeepIndentation( bool keep ); @@ -699,7 +704,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { Font* mFont; UIFontStyleConfig mFontStyleConfig; std::shared_ptr mDoc; - LineWrapping mLineWrapping; + DocumentView mDocView; Clock mBlinkTimer; Time mBlinkTime; bool mDirtyEditor{ false }; @@ -957,7 +962,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { UIMenuItem* menuAdd( UIPopUpMenu* menu, const String& translateString, const std::string& icon, const std::string& cmd ); - void drawMinimap( const Vector2f& start, const std::pair& lineRange ); + void drawMinimap( const Vector2f& start, const std::pair& docLineRange, + const std::pair& visibleLineRange ); bool isMinimapFileTooLarge() const; diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 9a6d918f3..f62334ddd 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -302,7 +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/doc/documentview.hpp ../../include/eepp/ui/models/model.hpp ../../include/eepp/ui/abstract/uiabstracttableview.hpp ../../include/eepp/ui/abstract/uiabstractview.hpp @@ -1117,8 +1117,8 @@ ../../src/eepp/ui/doc/textdocument.cpp ../../src/eepp/ui/doc/textformat.cpp ../../src/eepp/ui/doc/textundostack.cpp +../../src/eepp/ui/doc/documentview.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/doc/documentview.cpp similarity index 84% rename from src/eepp/ui/linewrapping.cpp rename to src/eepp/ui/doc/documentview.cpp index af5e8c71a..033614d95 100644 --- a/src/eepp/ui/linewrapping.cpp +++ b/src/eepp/ui/doc/documentview.cpp @@ -2,11 +2,11 @@ #include #include #include -#include +#include -namespace EE { namespace UI { +namespace EE { namespace UI { namespace Doc { -LineWrapMode LineWrapping::toLineWrapMode( std::string mode ) { +LineWrapMode DocumentView::toLineWrapMode( std::string mode ) { String::toLowerInPlace( mode ); if ( mode == "word" ) return LineWrapMode::Word; @@ -15,7 +15,7 @@ LineWrapMode LineWrapping::toLineWrapMode( std::string mode ) { return LineWrapMode::NoWrap; } -std::string LineWrapping::fromLineWrapMode( LineWrapMode mode ) { +std::string DocumentView::fromLineWrapMode( LineWrapMode mode ) { switch ( mode ) { case LineWrapMode::Letter: return "letter"; @@ -27,14 +27,14 @@ std::string LineWrapping::fromLineWrapMode( LineWrapMode mode ) { } } -LineWrapType LineWrapping::toLineWrapType( std::string type ) { +LineWrapType DocumentView::toLineWrapType( std::string type ) { String::toLowerInPlace( type ); if ( "line_breaking_column" == type ) return LineWrapType::LineBreakingColumn; return LineWrapType::Viewport; } -std::string LineWrapping::fromLineWrapType( LineWrapType type ) { +std::string DocumentView::fromLineWrapType( LineWrapType type ) { switch ( type ) { case LineWrapType::LineBreakingColumn: return "line_breaking_column"; @@ -44,7 +44,7 @@ std::string LineWrapping::fromLineWrapType( LineWrapType type ) { } } -Float LineWrapping::computeOffsets( const String& string, const FontStyleConfig& fontStyle, +Float DocumentView::computeOffsets( const String& string, const FontStyleConfig& fontStyle, Uint32 tabWidth ) { auto nonIndentPos = string.find_first_not_of( " \t\n\v\f\r" ); @@ -53,7 +53,7 @@ Float LineWrapping::computeOffsets( const String& string, const FontStyleConfig& return 0.f; } -LineWrapping::LineWrapInfo LineWrapping::computeLineBreaks( const String& string, +DocumentView::LineWrapInfo DocumentView::computeLineBreaks( const String& string, const FontStyleConfig& fontStyle, Float maxWidth, LineWrapMode mode, bool keepIndentation, @@ -128,7 +128,7 @@ LineWrapping::LineWrapInfo LineWrapping::computeLineBreaks( const String& string return info; } -LineWrapping::LineWrapInfo LineWrapping::computeLineBreaks( const TextDocument& doc, size_t line, +DocumentView::LineWrapInfo DocumentView::computeLineBreaks( const TextDocument& doc, size_t line, const FontStyleConfig& fontStyle, Float maxWidth, LineWrapMode mode, bool keepIndentation, @@ -137,61 +137,61 @@ LineWrapping::LineWrapInfo LineWrapping::computeLineBreaks( const TextDocument& keepIndentation, tabWidth ); } -LineWrapping::LineWrapping( std::shared_ptr doc, FontStyleConfig fontStyle, +DocumentView::DocumentView( std::shared_ptr doc, FontStyleConfig fontStyle, Config config ) : mDoc( std::move( doc ) ), mFontStyle( std::move( fontStyle ) ), mConfig( std::move( config ) ) {} -bool LineWrapping::isWrapEnabled() const { +bool DocumentView::isWrapEnabled() const { return mConfig.mode != LineWrapMode::NoWrap; } -void LineWrapping::setMaxWidth( Float maxWidth, bool forceReconstructBreaks ) { +void DocumentView::setMaxWidth( Float maxWidth, bool forceReconstructBreaks ) { if ( maxWidth != mMaxWidth ) { mMaxWidth = maxWidth; - reconstructBreaks(); + invalidateCache(); } else if ( forceReconstructBreaks || mPendingReconstruction ) { - reconstructBreaks(); + invalidateCache(); } } -void LineWrapping::setFontStyle( FontStyleConfig fontStyle ) { +void DocumentView::setFontStyle( FontStyleConfig fontStyle ) { if ( fontStyle != mFontStyle ) { mFontStyle = std::move( fontStyle ); - reconstructBreaks(); + invalidateCache(); } } -void LineWrapping::setLineWrapMode( LineWrapMode mode ) { +void DocumentView::setLineWrapMode( LineWrapMode mode ) { if ( mode != mConfig.mode ) { mConfig.mode = mode; - reconstructBreaks(); + invalidateCache(); } } -TextPosition LineWrapping::getDocumentLine( Int64 visibleIndex ) const { +TextPosition DocumentView::getDocumentLine( Int64 visibleIndex ) const { if ( mConfig.mode == LineWrapMode::NoWrap || mWrappedLines.empty() ) return { visibleIndex, 0 }; return mWrappedLines[eeclamp( visibleIndex, 0ll, eemax( static_cast( mWrappedLines.size() ) - 1, 0ll ) )]; } -Float LineWrapping::getLineOffset( Int64 docIdx ) const { +Float DocumentView::getLineOffset( Int64 docIdx ) const { if ( mConfig.mode == LineWrapMode::NoWrap || mWrappedLinesOffset.empty() ) return 0; return mWrappedLinesOffset[eeclamp( docIdx, 0ll, eemax( static_cast( mWrappedLinesOffset.size() ) - 1, 0ll ) )]; } -void LineWrapping::setConfig( Config config ) { +void DocumentView::setConfig( Config config ) { if ( config != mConfig ) { mConfig = std::move( config ); - reconstructBreaks(); + invalidateCache(); } } -void LineWrapping::reconstructBreaks() { +void DocumentView::invalidateCache() { if ( 0 == mMaxWidth || !mDoc ) return; @@ -236,7 +236,7 @@ void LineWrapping::reconstructBreaks() { mPendingReconstruction = false; } -Int64 LineWrapping::toWrappedIndex( Int64 docIdx, bool retLast ) const { +Int64 DocumentView::toWrappedIndex( Int64 docIdx, bool retLast ) const { if ( mConfig.mode == LineWrapMode::NoWrap || mWrappedLineToIndex.empty() ) return docIdx; auto idx = mWrappedLineToIndex[eeclamp( docIdx, 0ll, @@ -254,7 +254,7 @@ Int64 LineWrapping::toWrappedIndex( Int64 docIdx, bool retLast ) const { return idx; } -bool LineWrapping::isWrappedLine( Int64 docIdx ) const { +bool DocumentView::isWrappedLine( Int64 docIdx ) const { if ( isWrapEnabled() && mConfig.mode != LineWrapMode::NoWrap ) { Int64 wrappedIndex = toWrappedIndex( docIdx ); return wrappedIndex + 1 < static_cast( mWrappedLines.size() ) && @@ -263,7 +263,7 @@ bool LineWrapping::isWrappedLine( Int64 docIdx ) const { return false; } -LineWrapping::VisualLine LineWrapping::getVisualLine( Int64 docIdx ) const { +DocumentView::VisualLine DocumentView::getVisualLine( Int64 docIdx ) const { VisualLine line; if ( mConfig.mode == LineWrapMode::NoWrap ) { line.visualLines.push_back( { docIdx, 0 } ); @@ -280,17 +280,17 @@ LineWrapping::VisualLine LineWrapping::getVisualLine( Int64 docIdx ) const { return line; } -LineWrapping::VisualLineInfo LineWrapping::getVisualLineInfo( const TextPosition& pos, +DocumentView::VisualLineInfo DocumentView::getVisualLineInfo( const TextPosition& pos, bool allowVisualLineEnd ) const { if ( mConfig.mode == LineWrapMode::NoWrap ) { - LineWrapping::VisualLineInfo info; + DocumentView::VisualLineInfo info; info.visualIndex = pos.line(); info.range = mDoc->getLineRange( pos.line() ); return info; } Int64 fromIdx = toWrappedIndex( pos.line() ); Int64 toIdx = toWrappedIndex( pos.line(), true ); - LineWrapping::VisualLineInfo info; + DocumentView::VisualLineInfo info; for ( Int64 i = fromIdx; i < toIdx; i++ ) { Int64 fromCol = mWrappedLines[i].column(); Int64 toCol = i + 1 <= toIdx @@ -309,7 +309,7 @@ LineWrapping::VisualLineInfo LineWrapping::getVisualLineInfo( const TextPosition return info; } -TextRange LineWrapping::getVisualLineRange( Int64 visualLine ) const { +TextRange DocumentView::getVisualLineRange( Int64 visualLine ) const { if ( mConfig.mode == LineWrapMode::NoWrap ) return mDoc->getLineRange( visualLine ); auto start = getDocumentLine( visualLine ); @@ -323,32 +323,32 @@ TextRange LineWrapping::getVisualLineRange( Int64 visualLine ) const { return { start, end }; } -std::shared_ptr LineWrapping::getDocument() const { +std::shared_ptr DocumentView::getDocument() const { return mDoc; } -void LineWrapping::setDocument( const std::shared_ptr& doc ) { +void DocumentView::setDocument( const std::shared_ptr& doc ) { if ( mDoc != doc ) { mDoc = doc; - reconstructBreaks(); + invalidateCache(); } } -bool LineWrapping::isPendingReconstruction() const { +bool DocumentView::isPendingReconstruction() const { return mPendingReconstruction; } -void LineWrapping::setPendingReconstruction( bool pendingReconstruction ) { +void DocumentView::setPendingReconstruction( bool pendingReconstruction ) { mPendingReconstruction = pendingReconstruction; } -void LineWrapping::clear() { +void DocumentView::clear() { mWrappedLines.clear(); mWrappedLineToIndex.clear(); mWrappedLinesOffset.clear(); } -void LineWrapping::updateBreaks( Int64 fromLine, Int64 toLine, Int64 numLines ) { +void DocumentView::updateCache( Int64 fromLine, Int64 toLine, Int64 numLines ) { if ( mConfig.mode == LineWrapMode::NoWrap ) return; // Get affected wrapped range @@ -410,7 +410,7 @@ void LineWrapping::updateBreaks( Int64 fromLine, Int64 toLine, Int64 numLines ) auto wrappedLinesToIndex = mWrappedLineToIndex; auto wrappedOffset = mWrappedLinesOffset; - reconstructBreaks(); + invalidateCache(); eeASSERT( wrappedLines == mWrappedLines ); eeASSERT( wrappedLinesToIndex == mWrappedLineToIndex ); @@ -418,8 +418,8 @@ void LineWrapping::updateBreaks( Int64 fromLine, Int64 toLine, Int64 numLines ) #endif } -size_t LineWrapping::getTotalLines() const { +size_t DocumentView::getTotalLines() const { return mConfig.mode == LineWrapMode::NoWrap ? mDoc->linesCount() : mWrappedLines.size(); } -}} // namespace EE::UI +}}} // namespace EE::UI::Doc diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 16fceece4..4ce71ed61 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -119,7 +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, {} ), + mDocView( mDoc, mFontStyleConfig, {} ), mBlinkTime( Seconds( 0.5f ) ), mTabWidth( 4 ), mMouseWheelScroll( 50 ), @@ -193,7 +193,7 @@ UICodeEditor::~UICodeEditor() { while ( mHighlightWordProcessing ) Sys::sleep( Milliseconds( 0.1 ) ); - mLineWrapping.setDocument( nullptr ); + mDocView.setDocument( nullptr ); if ( mDoc.use_count() == 1 ) { DocEvent event( this, mDoc.get(), Event::OnDocumentClosed ); sendEvent( &event ); @@ -242,8 +242,8 @@ void UICodeEditor::draw() { if ( mDirtyEditor ) updateEditor(); - if ( mLineWrapping.isPendingReconstruction() ) - mLineWrapping.reconstructBreaks(); + if ( mDocView.isPendingReconstruction() ) + mDocView.invalidateCache(); Color col; auto lineRange = getVisibleLineRange(); @@ -274,13 +274,13 @@ void UICodeEditor::draw() { for ( const auto& sel : mDoc->getSelections() ) { primitives.setColor( Color( mCurrentLineBackgroundColor ).blendAlpha( mAlpha ) ); Float height = 1; - if ( mLineWrapping.isWrappedLine( sel.start().line() ) ) - height = mLineWrapping.getVisualLine( sel.start().line() ).visualLines.size(); - primitives.drawRectangle( Rectf( - Vector2f( startScroll.x + mScroll.x, - startScroll.y + - mLineWrapping.toWrappedIndex( sel.start().line() ) * lineHeight ), - Sizef( mSize.getWidth(), lineHeight * height ) ) ); + if ( mDocView.isWrappedLine( sel.start().line() ) ) + height = mDocView.getVisualLine( sel.start().line() ).visualLines.size(); + primitives.drawRectangle( + Rectf( Vector2f( startScroll.x + mScroll.x, + startScroll.y + + mDocView.toWrappedIndex( sel.start().line() ) * lineHeight ), + Sizef( mSize.getWidth(), lineHeight * height ) ) ); } } @@ -336,7 +336,7 @@ void UICodeEditor::draw() { Vector2f curScroll( { startScroll.x, static_cast( startScroll.y + - lineHeight * (double)mLineWrapping.toWrappedIndex( i ) ) } ); + lineHeight * (double)mDocView.toWrappedIndex( i ) ) } ); for ( auto& plugin : mPlugins ) plugin->drawBeforeLineText( this, i, curScroll, charSize, lineHeight ); @@ -382,7 +382,7 @@ void UICodeEditor::draw() { } if ( mMinimapEnabled ) - drawMinimap( screenStart, lineRange ); + drawMinimap( screenStart, lineRange, visualLineRange ); if ( mLocked && mDisplayLockedIcon ) drawLockedIcon( start ); @@ -483,8 +483,8 @@ bool UICodeEditor::loadAsyncFromFile( } ); } - if ( mLineWrapping.isWrapEnabled() ) - mLineWrapping.setPendingReconstruction( true ); + if ( mDocView.isWrapEnabled() ) + mDocView.setPendingReconstruction( true ); runOnMainThread( [this, onLoaded, wasLocked, success] { if ( !wasLocked ) @@ -575,13 +575,13 @@ UICodeEditor* UICodeEditor::setFont( Font* font ) { void UICodeEditor::onFontChanged() { udpateGlyphWidth(); - mLineWrapping.setFontStyle( mFontStyleConfig ); + mDocView.setFontStyle( mFontStyleConfig ); invalidateDraw(); } void UICodeEditor::onFontStyleChanged() { udpateGlyphWidth(); - mLineWrapping.setFontStyle( mFontStyleConfig ); + mDocView.setFontStyle( mFontStyleConfig ); invalidateDraw(); } @@ -595,10 +595,10 @@ void UICodeEditor::onDocumentLoaded( TextDocument* ) { void UICodeEditor::invalidateLineWrapMaxWidth( bool force ) { switch ( mLineWrapType ) { case LineWrapType::Viewport: - mLineWrapping.setMaxWidth( getViewportWidth(), force ); + mDocView.setMaxWidth( getViewportWidth(), force ); break; case LineWrapType::LineBreakingColumn: - mLineWrapping.setMaxWidth( getGlyphWidth() * mLineBreakingColumn, force ); + mDocView.setMaxWidth( getGlyphWidth() * mLineBreakingColumn, force ); break; } } @@ -623,7 +623,7 @@ void UICodeEditor::onDocumentLoaded() { void UICodeEditor::onDocumentReset( TextDocument* ) { DocEvent event( this, mDoc.get(), Event::OnDocumentReset ); sendEvent( &event ); - mLineWrapping.clear(); + mDocView.clear(); invalidateEditor(); invalidateDraw(); invalidateLongestLineWidth(); @@ -737,9 +737,9 @@ const Uint32& UICodeEditor::getTabWidth() const { UICodeEditor* UICodeEditor::setTabWidth( const Uint32& tabWidth ) { if ( mTabWidth != tabWidth ) { mTabWidth = tabWidth; - auto config = mLineWrapping.getConfig(); + auto config = mDocView.getConfig(); config.tabWidth = tabWidth; - mLineWrapping.setConfig( config ); + mDocView.setConfig( config ); } return this; } @@ -895,12 +895,12 @@ TextDocument& UICodeEditor::getDocument() { void UICodeEditor::setDocument( std::shared_ptr doc ) { if ( mDoc.get() != doc.get() ) { mDoc->unregisterClient( this ); - mLineWrapping.setDocument( nullptr ); + mDocView.setDocument( nullptr ); if ( mDoc.use_count() == 1 ) onDocumentClosed( mDoc.get() ); mDoc = doc; mDoc->registerClient( this ); - mLineWrapping.setDocument( doc ); + mDocView.setDocument( doc ); onDocumentChanged(); if ( mDoc->isLoading() ) { mInvalidateOnLoaded = true; @@ -908,7 +908,7 @@ void UICodeEditor::setDocument( std::shared_ptr doc ) { invalidateEditor(); invalidateLongestLineWidth(); invalidateDraw(); - mLineWrapping.setDocument( mDoc ); + mDocView.setDocument( mDoc ); } } } @@ -928,8 +928,8 @@ void UICodeEditor::invalidateLongestLineWidth() { } void UICodeEditor::setLineWrapMode( LineWrapMode mode ) { - auto prevMode = mLineWrapping.getConfig().mode; - mLineWrapping.setLineWrapMode( mode ); + auto prevMode = mDocView.getConfig().mode; + mDocView.setLineWrapMode( mode ); if ( prevMode != mode && LineWrapMode::NoWrap == mode ) { invalidateLongestLineWidth(); } @@ -947,9 +947,9 @@ void UICodeEditor::setLineWrapType( LineWrapType lineWrapType ) { } void UICodeEditor::setLineWrapKeepIndentation( bool keep ) { - auto config = mLineWrapping.getConfig(); + auto config = mDocView.getConfig(); config.keepIndentation = keep; - mLineWrapping.setConfig( config ); + mDocView.setConfig( config ); } Uint32 UICodeEditor::onFocus( NodeFocusReason reason ) { @@ -1041,7 +1041,7 @@ void UICodeEditor::drawLockedIcon( const Vector2f start ) { } size_t UICodeEditor::getTotalVisibleLines() const { - return mLineWrapping.getTotalLines(); + return mDocView.getTotalLines(); } Uint32 UICodeEditor::onTextEditing( const TextEditingEvent& event ) { @@ -1099,7 +1099,7 @@ TextPosition UICodeEditor::resolveScreenPosition( const Vector2f& position, bool visibleLineIndex = eeclamp( visibleLineIndex, 0, (Int64)( getTotalVisibleLines() - 1 ) ); } - return TextPosition( mLineWrapping.getDocumentLine( visibleLineIndex ).line(), + return TextPosition( mDocView.getDocumentLine( visibleLineIndex ).line(), getColFromXOffset( visibleLineIndex, localPos.x ) ); } @@ -1645,7 +1645,7 @@ void UICodeEditor::onSizeChange() { UIWidget::onSizeChange(); invalidateEditor( false ); invalidateLineWrapMaxWidth( false ); - if ( mLineWrapping.isWrapEnabled() ) + if ( mDocView.isWrapEnabled() ) invalidateLongestLineWidth(); } @@ -1653,7 +1653,7 @@ void UICodeEditor::onPaddingChange() { UIWidget::onPaddingChange(); invalidateEditor( false ); invalidateLineWrapMaxWidth( false ); - if ( mLineWrapping.isWrapEnabled() ) + if ( mDocView.isWrapEnabled() ) invalidateLongestLineWidth(); } @@ -1685,8 +1685,8 @@ void UICodeEditor::findLongestLine() { Float UICodeEditor::getLineWidth( const Int64& docLine ) { if ( docLine >= (Int64)mDoc->linesCount() ) return 0; - if ( mLineWrapping.isWrappedLine( docLine ) ) { - auto vline = mLineWrapping.getVisualLine( docLine ); + if ( mDocView.isWrappedLine( docLine ) ) { + auto vline = mDocView.getVisualLine( docLine ); auto& line = mDoc->line( docLine ).getText(); Float width = 0; @@ -1849,7 +1849,7 @@ void UICodeEditor::onDocumentTextChanged( const DocumentContentChange& change ) invalidateDraw(); checkMatchingBrackets(); sendCommonEvent( Event::OnTextChanged ); - mLineWrapping.updateBreaks( change.range.start().line(), change.range.start().line(), 0 ); + mDocView.updateCache( change.range.start().line(), change.range.start().line(), 0 ); if ( !change.text.empty() ) { auto range = findLongestLineInRange( change.range ); @@ -1918,7 +1918,7 @@ void UICodeEditor::onDocumentClosed( TextDocument* doc ) { void UICodeEditor::onDocumentLineMove( const Int64& fromLine, const Int64& toLine, const Int64& numLines ) { - mLineWrapping.updateBreaks( fromLine, toLine, numLines ); + mDocView.updateCache( fromLine, toLine, numLines ); if ( !mFont || mFont->isMonospace() || mLinesWidthCache.empty() ) return; @@ -1959,10 +1959,9 @@ std::pair UICodeEditor::getVisibleLineRange( bool visualIndexes Int64 minLine = eemax( 0.f, eefloor( mScroll.y / lineHeight ) ); Int64 maxLine = eemin( eemax( getTotalVisibleLines() - 1.f, 0.f ), eefloor( ( mSize.getHeight() + mScroll.y ) / lineHeight ) + 1 ); - if ( !visualIndexes && mLineWrapping.isWrapEnabled() ) { - return std::make_pair( - (Uint64)mLineWrapping.getDocumentLine( minLine ).line(), - (Uint64)mLineWrapping.getDocumentLine( maxLine ).line() ); + if ( !visualIndexes && mDocView.isWrapEnabled() ) { + return std::make_pair( (Uint64)mDocView.getDocumentLine( minLine ).line(), + (Uint64)mDocView.getDocumentLine( maxLine ).line() ); } return std::make_pair( (Uint64)minLine, (Uint64)maxLine ); } @@ -1970,22 +1969,14 @@ std::pair UICodeEditor::getVisibleLineRange( bool visualIndexes TextRange UICodeEditor::getVisibleRange() const { auto visibleLineRange = getVisibleLineRange(); return mDoc->sanitizeRange( TextRange( - TextPosition( - visibleLineRange.first, - mDoc->endOfLine( { static_cast( visibleLineRange.first ), 0 } ).column() ), + TextPosition( visibleLineRange.first, 0 ), TextPosition( visibleLineRange.second, mDoc->endOfLine( { static_cast( visibleLineRange.second ), 0 } ).column() ) ) ); } -bool UICodeEditor::isLineVisible( const Uint64& line ) const { - auto range = getVisibleLineRange(); - return line >= range.first && line <= range.second; -} - int UICodeEditor::getVisibleLinesCount() const { - auto lines = getVisibleLineRange(); - return lines.second - lines.first; + return eefloor( mSize.getHeight() / getLineHeight() ) + 1; } const StyleSheetLength& UICodeEditor::getLineSpacing() const { @@ -2121,8 +2112,8 @@ Vector2f UICodeEditor::getTextPositionOffset( const TextPosition& position, std::optional lineHeight, bool allowVisualLineEnd ) const { Float lh = lineHeight ? *lineHeight : getLineHeight(); - if ( mLineWrapping.isWrappedLine( position.line() ) ) { - auto info = mLineWrapping.getVisualLineInfo( position, allowVisualLineEnd ); + if ( mDocView.isWrappedLine( position.line() ) ) { + auto info = mDocView.getVisualLineInfo( position, allowVisualLineEnd ); if ( mFont && !mFont->isMonospace() ) { const auto& line = mDoc->line( position.line() ).getText(); auto partialLine = @@ -2145,9 +2136,9 @@ Vector2f UICodeEditor::getTextPositionOffset( const TextPosition& position, x += glyphWidth; } } - auto firstWrappedIndex = mLineWrapping.toWrappedIndex( position.line() ); + auto firstWrappedIndex = mDocView.toWrappedIndex( position.line() ); if ( info.visualIndex != firstWrappedIndex ) { - x += mLineWrapping.getLineOffset( position.line() ); + x += mDocView.getLineOffset( position.line() ); } return { x, info.visualIndex * lh }; } @@ -2160,7 +2151,7 @@ Vector2f UICodeEditor::getTextPositionOffset( const TextPosition& position, mFont, getCharacterSize(), mDoc->line( position.line() ).getText(), mFontStyleConfig.Style, mTabWidth, mFontStyleConfig.OutlineThickness, false ) .x, - lh * mLineWrapping.toWrappedIndex( position.line() ) }; + lh * mDocView.toWrappedIndex( position.line() ) }; } const String& line = mDoc->line( position.line() ).getText(); @@ -2174,7 +2165,7 @@ Vector2f UICodeEditor::getTextPositionOffset( const TextPosition& position, x += glyphWidth; } } - return { x, lh * mLineWrapping.toWrappedIndex( position.line() ) }; + return { x, lh * mDocView.toWrappedIndex( position.line() ) }; } template size_t UICodeEditor::characterWidth( const StringType& str ) const { @@ -2697,13 +2688,13 @@ Int64 UICodeEditor::getColFromXOffset( Int64 visualLine, const Float& x ) const if ( x < 0 || !mFont || mDoc->isLoading() ) return 0; - TextPosition pos = mDoc->sanitizePosition( mLineWrapping.getDocumentLine( visualLine ) ); + TextPosition pos = mDoc->sanitizePosition( mDocView.getDocumentLine( visualLine ) ); - if ( mLineWrapping.isWrappedLine( pos.line() ) ) { - auto visualRange = mLineWrapping.getVisualLineRange( visualLine ); - auto firstVisualIndex = mLineWrapping.toWrappedIndex( visualRange.start().line() ); + if ( mDocView.isWrappedLine( pos.line() ) ) { + auto visualRange = mDocView.getVisualLineRange( visualLine ); + auto firstVisualIndex = mDocView.toWrappedIndex( visualRange.start().line() ); Float xOffset = firstVisualIndex != visualLine - ? mLineWrapping.getLineOffset( visualRange.start().line() ) + ? mDocView.getLineOffset( visualRange.start().line() ) : 0; auto line = mDoc->line( visualRange.start().line() ) @@ -2877,9 +2868,9 @@ TextPosition UICodeEditor::moveToLineOffset( const TextPosition& position, int o if ( xo.position != position ) xo.offset = getTextPositionOffsetSanitized( position ).x; - if ( mLineWrapping.isWrapEnabled() ) { - auto info = mLineWrapping.getVisualLineInfo( position ); - auto nextLine = mLineWrapping.getVisualLineRange( info.visualIndex + offset ); + if ( mDocView.isWrapEnabled() ) { + auto info = mDocView.getVisualLineInfo( position ); + auto nextLine = mDocView.getVisualLineRange( info.visualIndex + offset ); xo.position.setLine( nextLine.end().line() ); xo.position.setColumn( getColFromXOffset( info.visualIndex + offset, xo.offset ) ); return xo.position; @@ -2901,7 +2892,7 @@ void UICodeEditor::moveToNextLine() { void UICodeEditor::moveToStartOfLine() { for ( size_t i = 0; i < mDoc->getSelections().size(); ++i ) { auto selection = mDoc->getSelectionIndex( i ); - auto info = mLineWrapping.getVisualLineInfo( mDoc->getSelectionIndex( i ).start() ); + auto info = mDocView.getVisualLineInfo( mDoc->getSelectionIndex( i ).start() ); mDoc->setSelection( i, info.range.start() != selection.start() ? info.range.start() : mDoc->startOfLine( selection.start() ) ); @@ -2912,7 +2903,7 @@ void UICodeEditor::moveToStartOfLine() { void UICodeEditor::moveToEndOfLine() { for ( size_t i = 0; i < mDoc->getSelections().size(); ++i ) { auto selection = mDoc->getSelectionIndex( i ); - auto info = mLineWrapping.getVisualLineInfo( selection.start() ); + auto info = mDocView.getVisualLineInfo( selection.start() ); mDoc->setSelection( i, info.range.end() != selection.end() ? info.range.end() : mDoc->endOfLine( selection.end() ) ); @@ -2923,7 +2914,7 @@ void UICodeEditor::moveToEndOfLine() { void UICodeEditor::moveToStartOfContent() { for ( size_t i = 0; i < mDoc->getSelections().size(); ++i ) { TextPosition start = mDoc->getSelectionIndex( i ).start(); - auto info = mLineWrapping.getVisualLineInfo( start ); + auto info = mDocView.getVisualLineInfo( start ); if ( info.range.start().column() != 0 ) { mDoc->setSelection( i, info.range.start() != start ? info.range.start() : mDoc->startOfContent( start ) ); @@ -2940,7 +2931,7 @@ void UICodeEditor::moveToStartOfContent() { void UICodeEditor::selectToStartOfLine() { for ( size_t i = 0; i < mDoc->getSelections().size(); ++i ) { auto selection = mDoc->getSelectionIndex( i ); - auto info = mLineWrapping.getVisualLineInfo( mDoc->getSelectionIndex( i ).start() ); + auto info = mDocView.getVisualLineInfo( mDoc->getSelectionIndex( i ).start() ); mDoc->selectTo( i, info.range.start() != selection.start() ? info.range.start() : mDoc->startOfLine( selection.start() ) ); @@ -2951,7 +2942,7 @@ void UICodeEditor::selectToStartOfLine() { void UICodeEditor::selectToEndOfLine() { for ( size_t i = 0; i < mDoc->getSelections().size(); ++i ) { auto selection = mDoc->getSelectionIndex( i ); - auto info = mLineWrapping.getVisualLineInfo( selection.start() ); + auto info = mDocView.getVisualLineInfo( selection.start() ); mDoc->selectTo( i, info.range.end() != selection.start() ? info.range.end() : mDoc->endOfLine( selection.start() ) ); @@ -2962,7 +2953,7 @@ void UICodeEditor::selectToEndOfLine() { void UICodeEditor::selectToStartOfContent() { for ( size_t i = 0; i < mDoc->getSelections().size(); ++i ) { TextPosition start = mDoc->getSelectionIndex( i ).start(); - auto info = mLineWrapping.getVisualLineInfo( start ); + auto info = mDocView.getVisualLineInfo( start ); if ( info.range.start().column() != 0 ) { mDoc->selectTo( i, info.range.start() != start ? info.range.start() : mDoc->startOfContent( start ) ); @@ -2978,7 +2969,7 @@ void UICodeEditor::selectToStartOfContent() { void UICodeEditor::jumpLinesUp( int offset ) { for ( size_t i = 0; i < mDoc->getSelections().size(); ++i ) { TextPosition position = mDoc->getSelections()[i].start(); - if ( mLineWrapping.toWrappedIndex( position.line() ) == 0 ) { + if ( mDocView.toWrappedIndex( position.line() ) == 0 ) { mDoc->setSelection( i, mDoc->startOfDoc(), mDoc->startOfDoc() ); } else { mDoc->moveTo( i, moveToLineOffset( position, offset, i ) ); @@ -3446,8 +3437,8 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo } }; - if ( mLineWrapping.isWrappedLine( line ) ) { - auto vline = mLineWrapping.getVisualLine( line ); + if ( mDocView.isWrappedLine( line ) ) { + auto vline = mDocView.getVisualLine( line ); size_t curvline = 1; size_t lineLength = strLine.length(); size_t nextLineCol = vline.visualLines[curvline].column(); @@ -3600,14 +3591,14 @@ UICodeEditor::getTextRangeRectangles( const TextRange& range, const Vector2f& st for ( auto ln = startLine; ln <= endLine; ln++ ) { const String& line = mDoc->line( ln ).getText(); Rectf selRect; - if ( mLineWrapping.isWrappedLine( ln ) ) { - auto fromInfo = mLineWrapping.getVisualLineInfo( + if ( mDocView.isWrappedLine( ln ) ) { + auto fromInfo = mDocView.getVisualLineInfo( ln == range.start().line() ? range.start() : mDoc->startOfLine( { ln, 0 } ) ); - auto toInfo = mLineWrapping.getVisualLineInfo( + auto toInfo = mDocView.getVisualLineInfo( ln == range.end().line() ? range.end() : mDoc->endOfLine( { ln, 0 } ) ); for ( Int64 visibleIdx = fromInfo.visualIndex; visibleIdx <= toInfo.visualIndex; visibleIdx++ ) { - auto info = mLineWrapping.getDocumentLine( visibleIdx ); + auto info = mDocView.getDocumentLine( visibleIdx ); Vector2f startOffset; Vector2f endOffset; if ( ln == range.start().line() && fromInfo.range.start().line() == ln && @@ -3623,7 +3614,7 @@ UICodeEditor::getTextRangeRectangles( const TextRange& range, const Vector2f& st toInfo.visualIndex == visibleIdx ) { endOffset = getTextPositionOffset( range.end(), lh ); } else { - auto nextInfo = mLineWrapping.getDocumentLine( visibleIdx + 1 ); + auto nextInfo = mDocView.getDocumentLine( visibleIdx + 1 ); if ( nextInfo.line() == info.line() ) { endOffset = getTextPositionOffset( { info.line(), nextInfo.column() }, lh, true ); @@ -3703,8 +3694,7 @@ void UICodeEditor::drawLineNumbers( const std::pair& lineRange, } Text::draw( pos, Vector2f( screenStart.x + mLineNumberPaddingLeft, - startScroll.y + - lineHeight * (double)mLineWrapping.toWrappedIndex( i ) + + startScroll.y + lineHeight * (double)mDocView.toWrappedIndex( i ) + lineOffset ), mFontStyleConfig.Font, fontSize, ( i >= selection.start().line() && i <= selection.end().line() ) @@ -3742,7 +3732,7 @@ void UICodeEditor::drawWhitespaces( const std::pair& lineRange, cpoint->setColor( color ); for ( int index = lineRange.first; index <= lineRange.second; index++ ) { const auto& text = mDoc->line( index ).getText(); - if ( mLineWrapping.isWrappedLine( index ) ) { + if ( mDocView.isWrappedLine( index ) ) { for ( size_t i = 0; i < text.size(); i++ ) { if ( ' ' == text[i] ) { auto offset = @@ -3757,8 +3747,7 @@ void UICodeEditor::drawWhitespaces( const std::pair& lineRange, } } else { Vector2f position( - { startScroll.x, - startScroll.y + lineHeight * mLineWrapping.toWrappedIndex( index ) } ); + { startScroll.x, startScroll.y + lineHeight * mDocView.toWrappedIndex( index ) } ); for ( size_t i = 0; i < text.size(); i++ ) { if ( position.x + mScroll.x + ( text[i] == '\t' ? tabWidth : glyphW ) >= mScreenPos.x && @@ -3817,7 +3806,7 @@ void UICodeEditor::drawIndentationGuides( const std::pair& lineRange, : mDoc->getIndentWidth(); for ( int index = lineRange.first; index <= lineRange.second; index++ ) { Vector2f position( - { startScroll.x, startScroll.y + lineHeight * mLineWrapping.toWrappedIndex( index ) } ); + { startScroll.x, startScroll.y + lineHeight * mDocView.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 } ) ); @@ -3836,7 +3825,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 * mLineWrapping.toWrappedIndex( index ) } ); + startScroll.y + lineHeight * mDocView.toWrappedIndex( index ) } ); nl->draw( Vector2f( position.x, position.y ) ); } } @@ -4078,13 +4067,13 @@ Rectf UICodeEditor::getMinimapRect( const Vector2f& start ) const { static const SyntaxStyleType SYNTAX_NORMAL = SyntaxStyleTypes::Normal; -void UICodeEditor::drawMinimap( const Vector2f& start, const std::pair& ) { +void UICodeEditor::drawMinimap( const Vector2f& start, const std::pair&, + const std::pair& visibleLineRange ) { Float charHeight = PixelDensity::getPixelDensity() * mMinimapConfig.scale; Float charSpacing = eemax( 1.f, eefloor( 0.8 * PixelDensity::getPixelDensity() * mMinimapConfig.scale ) ); Float lineSpacing = getMinimapLineSpacing(); Rectf rect( getMinimapRect( start ) ); - auto visibleLineRange = getVisibleLineRange( true ); int visibleLinesCount = ( visibleLineRange.second - visibleLineRange.first ); int visibleLinesStart = visibleLineRange.first; Float scrollerHeight = visibleLinesCount * lineSpacing; @@ -4178,11 +4167,11 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const std::pairquadsSetColor( backgroundColor ); Int64 lineSkip = -1; for ( const auto& range : ranges ) { - if ( !mLineWrapping.isWrapEnabled() && range.start().column() > maxVisibleColumn ) + if ( !mDocView.isWrapEnabled() && range.start().column() > maxVisibleColumn ) continue; - auto rangeStart = mLineWrapping.getVisualLineInfo( range.start() ); - auto rangeEnd = mLineWrapping.getVisualLineInfo( range.end() ); + auto rangeStart = mDocView.getVisualLineInfo( range.start() ); + auto rangeEnd = mDocView.getVisualLineInfo( range.end() ); if ( minimapStartLine > rangeEnd.visualIndex || endidx < rangeStart.visualIndex ) continue; @@ -4262,8 +4251,16 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const std::pairminimapDrawBefore( this, docRange, docViewRange, { rect.Left, lineY }, + { rect.getWidth(), charHeight }, charSpacing, gutterWidth, + drawTextRanges ); + } for ( Int64 line = minimapStartDocLine; line <= endDocIdx; line++ ) { batchSyntaxType = &SYNTAX_NORMAL; @@ -4273,20 +4270,14 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const std::pairminimapDrawBeforeLineText( this, line, { rect.Left, lineY }, - { rect.getWidth(), charHeight }, charSpacing, - gutterWidth, drawTextRanges ); - } - const auto& tokens = mDoc->getHighlighter()->getLine( line, false ); const auto& text = mDoc->line( line ).getText(); Int64 pos = 0; - bool wrappedLine = mLineWrapping.isWrappedLine( line ); + bool wrappedLine = mDocView.isWrappedLine( line ); if ( wrappedLine ) { bool outOfRange = false; - auto vline = mLineWrapping.getVisualLine( line ); + auto vline = mDocView.getVisualLine( line ); size_t curvline = 1; Int64 nextLineCol = vline.visualLines[curvline].column(); Int64 lineLength = text.size(); @@ -4393,16 +4384,16 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const std::pairminimapDrawAfterLineText( this, line, { rect.Left, lineY }, - { rect.getWidth(), charHeight }, charSpacing, - gutterWidth, drawTextRanges ); - } - if ( !wrappedLine ) lineY += lineSpacing; } + for ( auto* plugin : mPlugins ) { + plugin->minimapDrawAfter( this, docRange, docViewRange, { rect.Left, lineY }, + { rect.getWidth(), charHeight }, charSpacing, gutterWidth, + drawTextRanges ); + } + if ( mHighlightTextRange.isValid() && mHighlightTextRange.hasSelection() ) { drawTextRanges( { mHighlightTextRange }, Color( mMinimapSelectionColor ).blendAlpha( mAlpha ) ); @@ -4416,9 +4407,9 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const std::pairgetSelections().size(); ++i ) { const auto& selection = mDoc->getSelectionIndex( i ); Float selectionY = - rect.Top + ( mLineWrapping.getVisualLineInfo( selection.start() ).visualIndex - - minimapStartLine ) * - lineSpacing; + rect.Top + + ( mDocView.getVisualLineInfo( selection.start() ).visualIndex - minimapStartLine ) * + lineSpacing; BR->quadsSetColor( Color( mMinimapCurrentLineColor ).blendAlpha( mAlpha ) ); BR->batchQuad( { { rect.Left, selectionY }, { rect.getWidth(), lineSpacing } } ); } diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index b7e053287..3704a577f 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -140,9 +140,9 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath, editor.autoReloadOnDiskChange = ini.getValueB( "editor", "auto_reload_on_disk_change", false ); editor.wrapMode = - LineWrapping::toLineWrapMode( ini.getValue( "editor", "wrap_mode", "nowrap" ) ); + DocumentView::toLineWrapMode( ini.getValue( "editor", "wrap_mode", "nowrap" ) ); editor.wrapType = - LineWrapping::toLineWrapType( ini.getValue( "editor", "wrap_type", "viewport" ) ); + DocumentView::toLineWrapType( ini.getValue( "editor", "wrap_type", "viewport" ) ); editor.wrapKeepIndentation = ini.getValueB( "editor", "wrap_keep_indentation", true ); searchBarConfig.caseSensitive = ini.getValueB( "search_bar", "case_sensitive", false ); @@ -270,8 +270,8 @@ void AppConfig::save( const std::vector& recentFiles, ini.setValueB( "editor", "lines_relative_position", editor.linesRelativePosition ); ini.setValueB( "editor", "auto_reload_on_disk_change", editor.autoReloadOnDiskChange ); - ini.setValue( "editor", "wrap_mode", LineWrapping::fromLineWrapMode( editor.wrapMode ) ); - ini.setValue( "editor", "wrap_type", LineWrapping::fromLineWrapType( editor.wrapType ) ); + ini.setValue( "editor", "wrap_mode", DocumentView::fromLineWrapMode( editor.wrapMode ) ); + ini.setValue( "editor", "wrap_type", DocumentView::fromLineWrapType( editor.wrapType ) ); ini.setValueB( "editor", "wrap_keep_indentation", editor.wrapKeepIndentation ); ini.setValueB( "search_bar", "case_sensitive", searchBarConfig.caseSensitive ); diff --git a/src/tools/ecode/plugins/linter/linterplugin.cpp b/src/tools/ecode/plugins/linter/linterplugin.cpp index 004cbe2ef..a2c762898 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.cpp +++ b/src/tools/ecode/plugins/linter/linterplugin.cpp @@ -1105,31 +1105,29 @@ void LinterPlugin::drawAfterLineText( UICodeEditor* editor, const Int64& index, } } -void LinterPlugin::minimapDrawBeforeLineText( - UICodeEditor* editor, const Int64& index, const Vector2f& /*pos*/, const Vector2f& /*size*/, - const Float&, const Float&, - const std::function - drawTextRanges ) { +void LinterPlugin::minimapDrawBefore( UICodeEditor* editor, const DocumentLineRange& docLineRange, + const DocumentViewLineRange&, const Vector2f& /*linePos*/, + const Vector2f& /*lineSize*/, const Float& /*charWidth*/, + const Float& /*gutterWidth*/, + const DrawTextRangesFn& drawTextRanges ) { Lock l( mMatchesMutex ); auto matchIt = mMatches.find( editor->getDocumentRef().get() ); if ( matchIt == mMatches.end() ) return; - const std::map>& map = matchIt->second; - auto lineIt = map.find( index ); - if ( lineIt == map.end() ) - return; TextDocument* doc = matchIt->first; - const std::vector& matches = lineIt->second; - for ( const auto& match : matches ) { - if ( match.lineCache != doc->line( index ).getHash() ) - return; - Color col( - editor->getColorScheme().getEditorSyntaxStyle( getMatchString( match.type ) ).color ); - col.blendAlpha( 100 ); - drawTextRanges( match.range, col, true ); - break; + for ( const auto& matches : matchIt->second ) { + for ( const auto& match : matches.second ) { + if ( match.range.intersectsLineRange( docLineRange ) ) { + if ( match.lineCache != doc->line( match.range.start().line() ).getHash() ) + return; + Color col( editor->getColorScheme() + .getEditorSyntaxStyle( getMatchString( match.type ) ) + .color ); + col.blendAlpha( 100 ); + drawTextRanges( match.range, col, true ); + } + } } } diff --git a/src/tools/ecode/plugins/linter/linterplugin.hpp b/src/tools/ecode/plugins/linter/linterplugin.hpp index 6a3ebcec5..3a1cd2efd 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.hpp +++ b/src/tools/ecode/plugins/linter/linterplugin.hpp @@ -84,10 +84,11 @@ class LinterPlugin : public Plugin { void drawAfterLineText( UICodeEditor* editor, const Int64& index, Vector2f position, const Float& fontSize, const Float& lineHeight ); - void minimapDrawBeforeLineText( - UICodeEditor*, const Int64&, const Vector2f&, const Vector2f&, const Float&, const Float&, - const std::function /* drawTextRanges */ ); + void minimapDrawBefore( UICodeEditor* /*editor*/, const DocumentLineRange&, + const DocumentViewLineRange&, const Vector2f& /*linePos*/, + const Vector2f& /*lineSize*/, const Float& /*charWidth*/, + const Float& /*gutterWidth*/, + const DrawTextRangesFn& /* drawTextRanges */ ); void update( UICodeEditor* ); diff --git a/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp b/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp index 9975025b3..ee11d240b 100644 --- a/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp +++ b/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp @@ -133,6 +133,19 @@ bool XMLToolsPlugin::isOverMatch( TextDocument* doc, const Int64& index ) const return true; } +bool XMLToolsPlugin::isVisibleInRange( TextDocument* doc, const DocumentLineRange& docLineRange ) { + if ( mMatches.empty() ) + return false; + auto clientIt = mMatches.find( doc ); + if ( clientIt == mMatches.end() ) + return false; + const ClientMatch& match = clientIt->second; + if ( !match.matchBracket.inSameLine() && !match.currentBracket.inSameLine() ) + return false; + return match.matchBracket.intersectsLineRange( docLineRange ) || + match.currentBracket.intersectsLineRange( docLineRange ); +} + static bool isClosedTag( TextDocument* doc, TextPosition start ) { SyntaxHighlighter* highlighter = doc->getHighlighter(); TextPosition endOfDoc = doc->endOfDoc(); @@ -367,23 +380,19 @@ void XMLToolsPlugin::drawBeforeLineText( UICodeEditor* editor, const Int64& inde } } -void XMLToolsPlugin::minimapDrawAfterLineText( - UICodeEditor* editor, const Int64& index, const Vector2f& /*pos*/, const Vector2f& /*size*/, - const Float&, const Float&, - const std::function - drawTextRanges ) { - if ( !isOverMatch( &editor->getDocument(), index ) ) +void XMLToolsPlugin::minimapDrawAfter( UICodeEditor* editor, const DocumentLineRange& docLineRange, + const DocumentViewLineRange&, const Vector2f& /*linePos*/, + const Vector2f& /*lineSize*/, const Float& /*charWidth*/, + const Float& /*gutterWidth*/, + const DrawTextRangesFn& drawTextRanges ) { + if ( !isVisibleInRange( &editor->getDocument(), docLineRange ) ) return; Primitives p; Color color( editor->getColorScheme().getEditorSyntaxStyle( "matching_bracket"_sst ).color ); Color blendedColor( Color( color, 50 ) ); p.setColor( blendedColor ); - const ClientMatch& match = mMatches[&editor->getDocument()]; for ( const auto& range : { match.matchBracket, match.currentBracket } ) { - if ( range.start().line() != index || !range.inSameLine() ) - continue; drawTextRanges( range, blendedColor, true ); } } diff --git a/src/tools/ecode/plugins/xmltools/xmltoolsplugin.hpp b/src/tools/ecode/plugins/xmltools/xmltoolsplugin.hpp index 85b7dd848..9ddc69755 100644 --- a/src/tools/ecode/plugins/xmltools/xmltoolsplugin.hpp +++ b/src/tools/ecode/plugins/xmltools/xmltoolsplugin.hpp @@ -43,10 +43,10 @@ class XMLToolsPlugin : public PluginBase { void drawBeforeLineText( UICodeEditor* editor, const Int64& index, Vector2f position, const Float& fontSize, const Float& lineHeight ) override; - void minimapDrawAfterLineText( - UICodeEditor*, const Int64&, const Vector2f&, const Vector2f&, const Float&, const Float&, - const std::function /* drawTextRanges */ ) override; + void minimapDrawAfter( UICodeEditor*, const DocumentLineRange&, const DocumentViewLineRange&, + const Vector2f& /*linePos*/, const Vector2f& /*lineSize*/, + const Float& /*charWidth*/, const Float& /*gutterWidth*/, + const DrawTextRangesFn& ) override; protected: bool mHighlightMatch{ true }; @@ -115,6 +115,8 @@ class XMLToolsPlugin : public PluginBase { virtual void onUnregisterDocument( TextDocument* doc ) override; bool isOverMatch( TextDocument* doc, const Int64& index ) const; + + bool isVisibleInRange( TextDocument* doc, const DocumentLineRange& docLineRange ); }; } // namespace ecode diff --git a/src/tools/ecode/settingsmenu.cpp b/src/tools/ecode/settingsmenu.cpp index 3edc25e76..1f56a59fb 100644 --- a/src/tools/ecode/settingsmenu.cpp +++ b/src/tools/ecode/settingsmenu.cpp @@ -1237,17 +1237,17 @@ UIMenu* SettingsMenu::createViewMenu() { if ( mLineWrapMenu->getCount() == 0 ) { UIPopUpMenu* wrapModeMenu = UIPopUpMenu::New(); wrapModeMenu->addRadioButton( i18n( "no_wrap", "No Wrap" ) ) - ->setId( LineWrapping::fromLineWrapMode( LineWrapMode::NoWrap ) ); + ->setId( DocumentView::fromLineWrapMode( LineWrapMode::NoWrap ) ); wrapModeMenu->addRadioButton( i18n( "wrap_word", "Word wrap" ) ) - ->setId( LineWrapping::fromLineWrapMode( LineWrapMode::Word ) ); + ->setId( DocumentView::fromLineWrapMode( LineWrapMode::Word ) ); wrapModeMenu->addRadioButton( i18n( "wrap_letter", "Letter wrap" ) ) - ->setId( LineWrapping::fromLineWrapMode( LineWrapMode::Letter ) ); + ->setId( DocumentView::fromLineWrapMode( LineWrapMode::Letter ) ); wrapModeMenu->on( Event::OnItemClicked, [this]( const Event* event ) { if ( !event->getNode()->isType( UI_TYPE_MENUITEM ) ) return; UIMenuItem* item = event->getNode()->asType(); - LineWrapMode mode = LineWrapping::toLineWrapMode( item->getId() ); + LineWrapMode mode = DocumentView::toLineWrapMode( item->getId() ); mApp->getConfig().editor.wrapMode = mode; mApp->getSplitter()->forEachEditor( [mode]( UICodeEditor* editor ) { editor->setLineWrapMode( mode ); } ); @@ -1258,16 +1258,16 @@ UIMenu* SettingsMenu::createViewMenu() { UIPopUpMenu* wrapTypeMenu = UIPopUpMenu::New(); wrapTypeMenu->addRadioButton( i18n( "viewport", "Viewport" ) ) - ->setId( LineWrapping::fromLineWrapType( LineWrapType::Viewport ) ); + ->setId( DocumentView::fromLineWrapType( LineWrapType::Viewport ) ); wrapTypeMenu ->addRadioButton( i18n( "line_breaking_column", "Line Breaking Column" ) ) - ->setId( LineWrapping::fromLineWrapType( LineWrapType::LineBreakingColumn ) ); + ->setId( DocumentView::fromLineWrapType( LineWrapType::LineBreakingColumn ) ); wrapTypeMenu->on( Event::OnItemClicked, [this]( const Event* event ) { if ( !event->getNode()->isType( UI_TYPE_MENUITEM ) ) return; UIMenuItem* item = event->getNode()->asType(); - LineWrapType type = LineWrapping::toLineWrapType( item->getId() ); + LineWrapType type = DocumentView::toLineWrapType( item->getId() ); mApp->getConfig().editor.wrapType = type; mApp->getSplitter()->forEachEditor( [type]( UICodeEditor* editor ) { editor->setLineWrapType( type ); } ); @@ -1305,11 +1305,11 @@ UIMenu* SettingsMenu::createViewMenu() { const auto& cfg = mApp->getConfig(); - wrapModeMenu->find( LineWrapping::fromLineWrapMode( cfg.editor.wrapMode ) ) + wrapModeMenu->find( DocumentView::fromLineWrapMode( cfg.editor.wrapMode ) ) ->asType() ->setActive( true ); - wrapTypeMenu->find( LineWrapping::fromLineWrapType( cfg.editor.wrapType ) ) + wrapTypeMenu->find( DocumentView::fromLineWrapType( cfg.editor.wrapType ) ) ->asType() ->setActive( true );