From 7ec6e3cf1f57c7de2d9d5387f273ace8467ccdfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 19 Apr 2026 00:52:03 -0300 Subject: [PATCH] Greatly improved signature help rendering, now allows to render in multi-line with text-wrapped and it's enabled by default. Added new options for the Auto Complete Plugin: * **max_signature_helper_width**: The maximum width in stylesheet length of the signature helper (default value: "90%"). * **max_suggestion_documentation_width**: The maximum width in stylesheet length of the currently selected suggestion item documentation (default value: "100%"). * **signature_help_multi_line**: Enables the signature help to be rendered in multiple lines if needed (wraps text), otherwise it will render in a single line and ensure the current parameter is visible. * **suggestion_documentation**: Enables the suggestion item documentation. (SpartanJ/ecode#874). --- include/eepp/graphics/richtext.hpp | 2 +- include/eepp/graphics/text.hpp | 23 +-- include/eepp/graphics/textselectionrange.hpp | 12 ++ include/eepp/ui/doc/textrange.hpp | 13 +- include/eepp/ui/uitextview.hpp | 2 +- src/eepp/graphics/richtext.cpp | 4 +- src/eepp/graphics/text.cpp | 24 +-- src/eepp/ui/doc/textrange.cpp | 69 ++++++++ src/tests/unit_tests/fontrendering.cpp | 10 +- .../autocomplete/autocompleteplugin.cpp | 156 +++++++++++------- .../autocomplete/autocompleteplugin.hpp | 10 +- 11 files changed, 219 insertions(+), 106 deletions(-) create mode 100644 include/eepp/graphics/textselectionrange.hpp diff --git a/include/eepp/graphics/richtext.hpp b/include/eepp/graphics/richtext.hpp index 4cfba07cd..d803b5f63 100644 --- a/include/eepp/graphics/richtext.hpp +++ b/include/eepp/graphics/richtext.hpp @@ -169,7 +169,7 @@ class EE_API RichText : public Drawable { Vector2f findCharacterPos( Int64 index ) const; /** @return A list of rectangles that cover the selection. */ - std::vector getSelectionRects() const; + SmallVector getSelectionRects() const; /** @return The current selection as a string. */ String getSelectionString() const; diff --git a/include/eepp/graphics/text.hpp b/include/eepp/graphics/text.hpp index 8af41c9cf..b832f861d 100644 --- a/include/eepp/graphics/text.hpp +++ b/include/eepp/graphics/text.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -25,11 +26,6 @@ struct WhitespaceDisplayConfig { std::optional tabOffset; }; -struct TextSelectionRange { - Int64 start{ 0 }; - Int64 end{ 0 }; -}; - class EE_API Text { public: static bool TextShaperEnabled; @@ -126,14 +122,11 @@ class EE_API Text { TextDirection direction = TextDirection::Unspecified, const Vector2f& initialOffset = {} ); - static Vector2f findCharacterPos( std::size_t index, Font* font, const Uint32& fontSize, - const String& string, const Uint32& style, - const Uint32& tabWidth = 4, - const Float& outlineThickness = 0.f, - std::optional tabOffset = {}, bool allowNewLine = true, - Uint32 textHints = 0, - TextDirection direction = TextDirection::Unspecified, - const Vector2f& initialOffset = {} ); + static Vector2f findCharacterPos( + std::size_t index, Font* font, const Uint32& fontSize, const String& string, + const Uint32& style, const Uint32& tabWidth = 4, const Float& outlineThickness = 0.f, + std::optional tabOffset = {}, bool allowNewLine = true, Uint32 textHints = 0, + TextDirection direction = TextDirection::Unspecified, const Vector2f& initialOffset = {} ); static std::size_t findLastCharPosWithinLength( Font* font, const Uint32& fontSize, const String& string, @@ -250,7 +243,7 @@ class EE_API Text { Float getTextHeight(); /** @return The line spacing */ - Float getLineSpacing(); + Float getLineSpacing() const; /** Draw the cached text on screen */ void draw( const Float& X, const Float& Y, const Vector2f& scale = Vector2f::One, @@ -390,7 +383,7 @@ class EE_API Text { /** @return A list of rectangles that cover the selection of the string, each rectangle * has the line spacing height and covers the width of the selection. */ - std::vector getSelectionRects( TextSelectionRange range ); + SmallVector getSelectionRects( TextSelectionRange range ); protected: struct VertexCoords { diff --git a/include/eepp/graphics/textselectionrange.hpp b/include/eepp/graphics/textselectionrange.hpp new file mode 100644 index 000000000..31917c944 --- /dev/null +++ b/include/eepp/graphics/textselectionrange.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace EE::Graphics { + +struct TextSelectionRange { + Int64 start{ 0 }; + Int64 end{ 0 }; +}; + +} // namespace EE::Graphics diff --git a/include/eepp/ui/doc/textrange.hpp b/include/eepp/ui/doc/textrange.hpp index eb6b2cd29..33b2610a7 100644 --- a/include/eepp/ui/doc/textrange.hpp +++ b/include/eepp/ui/doc/textrange.hpp @@ -2,8 +2,11 @@ #define EE_UI_DOC_TEXTRANGE_HPP #include +#include #include +using namespace EE::Graphics; + namespace EE { namespace UI { namespace Doc { class EE_API TextRange { @@ -120,7 +123,12 @@ class EE_API TextRange { static TextRange convertToLineColumn( const std::string_view& text, Int64 startOffset, Int64 endOffset ); - Int64 minimumDistance(const TextRange& other) const; + Int64 minimumDistance( const TextRange& other ) const; + + static TextSelectionRange convertToOffset( const String::View& text, const TextRange& range ); + + static TextSelectionRange convertToOffset( const std::string_view& text, + const TextRange& range ); private: TextPosition mStart; @@ -133,6 +141,9 @@ class EE_API TextRange { template static TextRange convertToLineColumn( const StringType& text, Int64 startOffset, Int64 endOffset ); + + template + static TextSelectionRange convertToOffset( const StringType& text, const TextRange& range ); }; class EE_API TextRanges : public std::vector { diff --git a/include/eepp/ui/uitextview.hpp b/include/eepp/ui/uitextview.hpp index 423273ced..47490ad28 100644 --- a/include/eepp/ui/uitextview.hpp +++ b/include/eepp/ui/uitextview.hpp @@ -138,7 +138,7 @@ class EE_API UITextView : public UIWidget { Int32 mSelCurInit; Int32 mSelCurEnd; Uint32 mTextDrawHints{ 0 }; - std::vector mSelRectsCache; + SmallVector mSelRectsCache; Int32 mLastSelCurInit; Int32 mLastSelCurEnd; bool mSelecting; diff --git a/src/eepp/graphics/richtext.cpp b/src/eepp/graphics/richtext.cpp index 1bacef8cd..8bfc3705c 100644 --- a/src/eepp/graphics/richtext.cpp +++ b/src/eepp/graphics/richtext.cpp @@ -182,9 +182,9 @@ Vector2f RichText::findCharacterPos( Int64 index ) const { return { 0, 0 }; } -std::vector RichText::getSelectionRects() const { +SmallVector RichText::getSelectionRects() const { const_cast( this )->updateLayout(); - std::vector rects; + SmallVector rects; if ( mSelection.start == mSelection.end ) return rects; diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp index 78aee52c5..712f54f99 100644 --- a/src/eepp/graphics/text.cpp +++ b/src/eepp/graphics/text.cpp @@ -788,8 +788,7 @@ Vector2f Text::findCharacterPos( std::size_t index ) const { std::size_t visualLinesSize = mVisualLines.size(); std::size_t lineIndex = const_cast( this )->findVisualLineFromCharIndex( index ); - Float vspace = static_cast( - mFontStyleConfig.Font->getLineSpacing( mFontStyleConfig.CharacterSize ) ); + Float vspace = getLineSpacing(); Float y = lineIndex * vspace; Float centerDiffX = 0; @@ -857,7 +856,7 @@ Int32 Text::findCharacterFromPos( const Vector2i& pos, bool returnNearest ) cons const_cast( this )->ensureVisualLinesUpdate(); - Float vspace = mFontStyleConfig.Font->getLineSpacing( mFontStyleConfig.CharacterSize ); + Float vspace = getLineSpacing(); int lineIndex = std::floor( pos.y / vspace ); std::size_t visualLinesSize = mVisualLines.size(); @@ -1610,13 +1609,10 @@ Float Text::getTextWidth() { Float Text::getTextHeight() { cacheWidth(); - return NULL != mFontStyleConfig.Font - ? mFontStyleConfig.Font->getLineSpacing( mFontStyleConfig.CharacterSize ) * - ( mLinesWidth.empty() ? 1 : mLinesWidth.size() ) - : 0; + return getLineSpacing() * ( mLinesWidth.empty() ? 1 : mLinesWidth.size() ); } -Float Text::getLineSpacing() { +Float Text::getLineSpacing() const { return NULL != mFontStyleConfig.Font ? mFontStyleConfig.Font->getLineSpacing( mFontStyleConfig.CharacterSize ) : 0; @@ -1841,8 +1837,7 @@ void Text::ensureGeometryUpdate() { Glyph hglyph = mFontStyleConfig.Font->getGlyph( L' ', mFontStyleConfig.CharacterSize, bold, reqItalic ); Float hspace = static_cast( hglyph.advance ); - Float vspace = static_cast( - mFontStyleConfig.Font->getLineSpacing( mFontStyleConfig.CharacterSize ) ); + Float vspace = getLineSpacing(); Float x = mInitialOffset.x; Float y = mFontStyleConfig.CharacterSize; @@ -2750,7 +2745,7 @@ Uint32 Text::getTotalVertices() { for ( const auto& ch : mString ) { lineHasChars = true; - if ( ' ' == ch ) + if ( ' ' == ch ) skipped++; else if ( '\n' == ch || '\t' == ch || '\r' == ch ) { lineHasChars = false; @@ -2893,8 +2888,8 @@ size_t Text::findVisualLineFromCharIndex( size_t charIndex ) { return 0; } -std::vector Text::getSelectionRects( TextSelectionRange range ) { - std::vector rects; +SmallVector Text::getSelectionRects( TextSelectionRange range ) { + SmallVector rects; if ( range.start == range.end || !mFontStyleConfig.Font ) return rects; @@ -2912,8 +2907,7 @@ std::vector Text::getSelectionRects( TextSelectionRange range ) { ->getGlyph( ' ', mFontStyleConfig.CharacterSize, mFontStyleConfig.Style & Text::Bold, mFontStyleConfig.Style & Text::Italic ) .advance; - Float vspace = static_cast( - mFontStyleConfig.Font->getLineSpacing( mFontStyleConfig.CharacterSize ) ); + Float vspace = getLineSpacing(); for ( size_t i = startLine; i <= endLine; ++i ) { Float top = i * vspace; diff --git a/src/eepp/ui/doc/textrange.cpp b/src/eepp/ui/doc/textrange.cpp index 486c678e7..48aa95c5d 100644 --- a/src/eepp/ui/doc/textrange.cpp +++ b/src/eepp/ui/doc/textrange.cpp @@ -164,6 +164,75 @@ TextRange TextRange::convertToLineColumn( const std::string_view& text, Int64 st return convertToLineColumn( text, startOffset, endOffset ); } +template +TextSelectionRange TextRange::convertToOffset( const StringType& text, const TextRange& range ) { + if ( !range.isValid() ) + return { -1, -1 }; + + Int64 startOffset = -1; + Int64 endOffset = -1; + Int64 currentLine = 0; + Int64 currentCol = 0; + Int64 currentPos = 0; + size_t len = text.length(); + + const TextPosition& start = range.start(); + const TextPosition& end = range.end(); + + for ( size_t i = 0; i <= len; i++ ) { + // Exact match for line and column + if ( startOffset == -1 && currentLine == start.line() && currentCol == start.column() ) { + startOffset = currentPos; + } + + if ( endOffset == -1 && currentLine == end.line() && currentCol == end.column() ) { + endOffset = currentPos; + } + + if ( startOffset != -1 && endOffset != -1 ) + break; + + if ( i == len ) + break; + + if ( text[i] == '\n' ) { + // If the requested column is virtually out of bounds for this line, clamp to the line's + // end (the newline character's pos) + if ( startOffset == -1 && currentLine == start.line() && start.column() > currentCol ) { + startOffset = currentPos; + } + if ( endOffset == -1 && currentLine == end.line() && end.column() > currentCol ) { + endOffset = currentPos; + } + + currentLine++; + currentCol = 0; + } else { + currentCol++; + } + + currentPos++; + } + + // If the range requested lines beyond the text entirely, clamp to the very end of the text + if ( startOffset == -1 ) + startOffset = currentPos; + + if ( endOffset == -1 ) + endOffset = currentPos; + + return { startOffset, endOffset }; +} + +TextSelectionRange TextRange::convertToOffset( const String::View& text, const TextRange& range ) { + return convertToOffset( text, range ); +} + +TextSelectionRange TextRange::convertToOffset( const std::string_view& text, + const TextRange& range ) { + return convertToOffset( text, range ); +} + Int64 TextRange::minimumDistance( const TextRange& other ) const { if ( intersects( other ) ) return 0; diff --git a/src/tests/unit_tests/fontrendering.cpp b/src/tests/unit_tests/fontrendering.cpp index c84096327..c6d39e14b 100644 --- a/src/tests/unit_tests/fontrendering.cpp +++ b/src/tests/unit_tests/fontrendering.cpp @@ -1198,7 +1198,7 @@ UTEST( FontRendering, TextSelection ) { // Test 1: Single line selection (Line 1) { - std::vector rects = text.getSelectionRects( { 0, 4 } ); // "Line" + auto rects = text.getSelectionRects( { 0, 4 } ); // "Line" EXPECT_EQ( 1ul, rects.size() ); if ( !rects.empty() ) { EXPECT_EQ( 0, rects[0].Top ); @@ -1212,7 +1212,7 @@ UTEST( FontRendering, TextSelection ) { { // "Line 1\nLine 2" -> Indices: "Line 1" (0-5), "\n" (6), "Line 2" (7-12) // Select from index 2 ("n" in "Line 1") to index 9 ("i" in "Line 2") - std::vector rects = text.getSelectionRects( { 2, 9 } ); + auto rects = text.getSelectionRects( { 2, 9 } ); EXPECT_EQ( 2ul, rects.size() ); if ( rects.size() >= 2 ) { // First line rect: From index 2 to end of line 1 @@ -1227,8 +1227,7 @@ UTEST( FontRendering, TextSelection ) { // Test 3: Full selection { - std::vector rects = - text.getSelectionRects( { 0, static_cast( txt.size() ) } ); + auto rects = text.getSelectionRects( { 0, static_cast( txt.size() ) } ); EXPECT_EQ( 3ul, rects.size() ); } @@ -1243,8 +1242,7 @@ UTEST( FontRendering, TextSelection ) { EXPECT_GT( text.getVisualLineCount(), (Uint32)1 ); - std::vector rects = - text.getSelectionRects( { 0, static_cast( text.getString().size() ) } ); + auto rects = text.getSelectionRects( { 0, static_cast( text.getString().size() ) } ); EXPECT_EQ( (size_t)text.getVisualLineCount(), rects.size() ); } diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp index 84d4f7487..04e28f01e 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp @@ -183,6 +183,30 @@ void AutoCompletePlugin::load( PluginManager* pluginManager ) { if ( mMaxSuggestionDocumentationWidth.empty() ) mMaxSuggestionDocumentationWidth = "100%"; + + if ( config.contains( "max_signature_helper_width" ) ) + mMaxSignatureHelperWidth = config.value( "max_signature_helper_width", "90%" ); + else { + config["max_signature_helper_width"] = "90%"; + updateConfigFile = true; + } + + if ( mMaxSignatureHelperWidth.empty() ) + mMaxSignatureHelperWidth = "90%"; + + if ( config.contains( "signature_help_multi_line" ) ) + mSignatureHelpMultiLine = config.value( "signature_help_multi_line", true ); + else { + config["signature_help_multi_line"] = mSignatureHelpMultiLine; + updateConfigFile = true; + } + + if ( config.contains( "suggestion_documentation" ) ) + mSuggestionDocumentation = config.value( "suggestion_documentation", true ); + else { + config["suggestion_documentation"] = mSuggestionDocumentation; + updateConfigFile = true; + } } if ( mKeyBindings.empty() ) { @@ -853,7 +877,8 @@ AutoCompletePlugin::processSignatureHelp( const LSPSignatureHelp& signatureHelp // Convert the LSP Signature Help into our own object: // We will convert the UTF-8 label to UTF-32, then we will remove any new lines and extra spaces - // This guarantees that we always display a single line signature help + // This guarantees that we always display a single line signature help when requested (this is + // optional) SignatureHelp signatures; signatures.activeSignature = signatureHelp.activeSignature; signatures.activeParameter = signatureHelp.activeParameter; @@ -869,12 +894,17 @@ AutoCompletePlugin::processSignatureHelp( const LSPSignatureHelp& signatureHelp doc.textInput( initialLabel ); std::vector parameters; parameters.reserve( sig.parameters.size() ); - int skippedSelections = 0; + nsig.parameters.reserve( sig.parameters.size() ); + int skippedSelections = 0; for ( size_t i = 0; i < sig.parameters.size(); i++ ) { auto start = String::utf8ToCodepointPosition( sig.label, sig.parameters[i].start ); auto end = String::utf8ToCodepointPosition( sig.label, sig.parameters[i].end ); auto sel = TextRange::convertToLineColumn( initialLabel.view(), start, end ); + + nsig.parameters.emplace_back( + TextSelectionRange{ static_cast( start ), static_cast( end ) } ); + size_t index = i - skippedSelections; if ( i == 0 ) { @@ -890,29 +920,26 @@ AutoCompletePlugin::processSignatureHelp( const LSPSignatureHelp& signatureHelp } auto selections( doc.getSelections() ); - nsig.parameters.reserve( selections.size() ); - if ( 0 != doc.replaceAll( "\n", "" ) ) { + if ( !mSignatureHelpMultiLine && 0 != doc.replaceAll( "\n", "" ) ) { while ( 0 != doc.replaceAll( " ", " " ) ) ; nsig.label = doc.getLineTextWithoutNewLine( 0 ); + nsig.parameters.clear(); for ( const auto& param : parameters ) { auto res = doc.find( param ); - if ( res.isValid() ) - nsig.parameters.emplace_back( res.result ); + if ( res.isValid() ) { + nsig.parameters.push_back( + TextRange::convertToOffset( nsig.label.view(), res.result ) ); + } } } else { nsig.label = std::move( initialLabel ); - - if ( !sig.parameters.empty() ) { - for ( auto& sel : selections ) - nsig.parameters.emplace_back( sel ); - } } - signatures.signatures.emplace_back( nsig ); + signatures.signatures.emplace_back( std::move( nsig ) ); } editor->runOnMainThread( [this, editor, signatures = std::move( signatures )] { @@ -1018,7 +1045,6 @@ void AutoCompletePlugin::update( UICodeEditor* ) { void AutoCompletePlugin::drawSignatureHelp( UICodeEditor* editor, const Vector2f& startScroll, const Float& /*lineHeight*/, bool drawUp ) { - TextDocument& doc = editor->getDocument(); Primitives primitives; const SyntaxColorScheme& scheme = editor->getColorScheme(); @@ -1031,9 +1057,6 @@ void AutoCompletePlugin::drawSignatureHelp( UICodeEditor* editor, const Vector2f if ( curSigIdx >= (int)mSignatureHelp.signatures.size() ) return; auto curSig = mSignatureHelp.signatures[curSigIdx]; - Float vdiff = drawUp ? -mRowHeight : mRowHeight; - auto offset = editor->getTextPositionOffset( mSignatureHelpPosition ); - Vector2f pos( startScroll.x + offset.x, startScroll.y + offset.y + vdiff ); primitives.setColor( Color( selectedStyle.background ).blendAlpha( editor->getAlpha() ) ); String str; if ( mSignatureHelp.signatures.size() > 1 ) { @@ -1044,66 +1067,74 @@ void AutoCompletePlugin::drawSignatureHelp( UICodeEditor* editor, const Vector2f str = curSig.label; } - Rectf boxRect( pos, Sizef( editor->getTextWidth( str ) + mBoxPadding.Left + mBoxPadding.Right, - mRowHeight ) ); - if ( boxRect.getPosition().x + boxRect.getSize().getWidth() > - editor->getScreenPos().x + editor->getPixelsSize().getWidth() ) { - boxRect.setPosition( - { eefloor( editor->getScreenPos().x + editor->getPixelsSize().getWidth() - - boxRect.getSize().getWidth() ), - boxRect.getPosition().y } ); + mSignatureHelpText.setFont( editor->getFont() ); + mSignatureHelpText.setFontSize( editor->getFontSize() ); + mSignatureHelpText.setFillColor( normalStyle.color ); + mSignatureHelpText.setStyle( normalStyle.style ); + if ( mSignatureHelpText.setString( str ) ) { + SyntaxTokenizer::tokenizeText( doc.getSyntaxDefinition(), editor->getColorScheme(), + &mSignatureHelpText ); + } + + if ( mSignatureHelpMultiLine ) { + mSignatureHelpText.setLineWrapMode( LineWrapMode::Word ); + mSignatureHelpText.setLineWrapKeepIndentation( true ); + mSignatureHelpText.setMaxWrapWidth( editor->convertLength( + StyleSheetLength( mMaxSignatureHelperWidth ), editor->getPixelsSize().getWidth() ) ); + } + + Float boxWidth = mSignatureHelpText.getTextWidth() + mBoxPadding.Left + mBoxPadding.Right; + Float boxHeight = + mSignatureHelpText.getVisualLineCount() * mSignatureHelpText.getLineSpacing() + + mBoxPadding.Top + mBoxPadding.Bottom; + + Float vdiff = drawUp ? -boxHeight : mRowHeight; + auto offset = editor->getTextPositionOffset( mSignatureHelpPosition ); + + Vector2f pos( startScroll.x + offset.x, startScroll.y + offset.y + vdiff ); + Rectf boxRect( pos, Sizef( boxWidth, boxHeight ) ); + + Float screenRight = editor->getScreenPos().x + editor->getPixelsSize().getWidth(); + if ( boxRect.Right > screenRight ) { + boxRect.setPosition( { eefloor( screenRight - boxWidth ), boxRect.getPosition().y } ); if ( boxRect.getPosition().x < editor->getScreenPos().x ) boxRect.setPosition( { eefloor( editor->getScreenPos().x ), boxRect.getPosition().y } ); } bool hasParams = !curSig.parameters.empty(); - TextRange curParam = + + auto curParam = hasParams ? curSig.parameters[mSignatureHelp.activeParameter % curSig.parameters.size()] - : TextRange{}; - Rectf curParamRect; + : TextSelectionRange{}; + + SmallVector paramRects; if ( hasParams ) { - curParamRect = Rectf( - { { boxRect.getPosition().x + mBoxPadding.Left + - curParam.start().column() * editor->getGlyphWidth(), - boxRect.getPosition().y }, - { ( curParam.end().column() - curParam.start().column() ) * editor->getGlyphWidth(), - mRowHeight } } ); + paramRects = mSignatureHelpText.getSelectionRects( curParam ); - if ( !editor->getScreenRect().contains( - Rectf{ { curParamRect.getPosition().x + - ( curParam.end().column() - curParam.start().column() ) * - editor->getGlyphWidth(), - curParamRect.getPosition().y }, - curParamRect.getSize() } ) ) { - auto offset = editor->getTextPositionOffset( mSignatureHelpPosition ); - pos = { static_cast( startScroll.x - - curParam.start().column() * editor->getGlyphWidth() + - offset.x ), - static_cast( startScroll.y + offset.y + vdiff ) }; + if ( !paramRects.empty() ) { + for ( auto& r : paramRects ) + r.move( { boxRect.Left + mBoxPadding.Left, boxRect.Top + mBoxPadding.Top } ); - boxRect.setPosition( pos ); - - curParamRect.setPosition( { boxRect.getPosition().x + mBoxPadding.Left + - curParam.start().column() * editor->getGlyphWidth(), - boxRect.getPosition().y } ); + if ( !mSignatureHelpMultiLine && !editor->getScreenRect().contains( paramRects[0] ) ) { + paramRects[0].move( + { -( boxRect.Left + mBoxPadding.Left ), -( boxRect.Top + mBoxPadding.Top ) } ); + pos = { static_cast( startScroll.x + offset.x - paramRects[0].Left ), + static_cast( startScroll.y + offset.y + vdiff ) }; + boxRect.setPosition( pos ); + paramRects[0].setPosition( { boxRect.Left + mBoxPadding.Left + paramRects[0].Left, + boxRect.getPosition().y } ); + } } } primitives.drawRoundedRectangle( boxRect, 0.f, Vector2f::One, 6 ); - if ( hasParams && curParam.end() != curParam.start() && - curParam.end().column() < (int)str.size() ) { - primitives.setColor( matchingSelection.color ); - primitives.drawRoundedRectangle( curParamRect, 0.f, Vector2f::One, 6 ); - } + primitives.setColor( matchingSelection.color ); + for ( const auto& rect : paramRects ) + primitives.drawRoundedRectangle( rect, 0.f, Vector2f::One, 6 ); - Text text( "", editor->getFont(), editor->getFontSize() ); - text.setFillColor( normalStyle.color ); - text.setStyle( normalStyle.style ); - text.setString( str ); - SyntaxTokenizer::tokenizeText( doc.getSyntaxDefinition(), editor->getColorScheme(), &text ); - text.draw( boxRect.getPosition().x + mBoxPadding.Left, - boxRect.getPosition().y + mBoxPadding.Top ); + mSignatureHelpText.draw( boxRect.getPosition().x + mBoxPadding.Left, + boxRect.getPosition().y + mBoxPadding.Top ); } void AutoCompletePlugin::postDraw( UICodeEditor* editor, const Vector2f& startScroll, @@ -1220,7 +1251,8 @@ void AutoCompletePlugin::postDraw( UICodeEditor* editor, const Vector2f& startSc icon->setColor( iconColor ); } - if ( mSuggestionIndex == (int)i && !suggestion.documentation.value.empty() ) { + if ( mSuggestionDocumentation && mSuggestionIndex == (int)i && + !suggestion.documentation.value.empty() ) { mSuggestionDoc.setFillColor( normalStyle.color ); mSuggestionDoc.setStyle( normalStyle.style ); mSuggestionDoc.setFont( editor->getFont() ); diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp index e33512279..48aa88f16 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp @@ -62,7 +62,7 @@ class AutoCompletePlugin : public Plugin { "Auto complete shows the completion popup as you type, so you can fill " "in long words by typing only a few characters.", AutoCompletePlugin::New, - { 0, 2, 8 }, + { 0, 3, 0 }, AutoCompletePlugin::NewSync }; } @@ -152,7 +152,7 @@ class AutoCompletePlugin : public Plugin { struct SignatureInformation { String label; LSPMarkupContent documentation; - std::vector parameters; + std::vector parameters; }; struct SignatureHelp { @@ -169,11 +169,15 @@ class AutoCompletePlugin : public Plugin { std::unordered_map> mDocsUpdating; Mutex mDocsUpdatingMutex; Text mSuggestionDoc; + Text mSignatureHelpText; size_t mMaxLabelCharacters{ 100 }; String::HashType mConfigHash{ 0 }; std::unordered_map mKeyBindings; std::unordered_map mShortcuts; - std::string mMaxSuggestionDocumentationWidth; + std::string mMaxSuggestionDocumentationWidth{ "100%" }; + std::string mMaxSignatureHelperWidth{ "90%" }; + bool mSignatureHelpMultiLine{ true }; + bool mSuggestionDocumentation{ true }; Float mRowHeight{ 0 }; Rectf mBoxRect;