diff --git a/include/eepp/graphics/text.hpp b/include/eepp/graphics/text.hpp index 356989a16..7ebbd8f9a 100644 --- a/include/eepp/graphics/text.hpp +++ b/include/eepp/graphics/text.hpp @@ -110,11 +110,11 @@ class EE_API Text { Color FontShadowColor = Color( 0, 0, 0, 255 ), Uint32 characterSize = PixelDensity::dpToPx( 12 ) ); - void setString( const String::View& string ); + bool setString( const String::View& string ); - void setString( const String& string ); + bool setString( const String& string ); - void setString( String&& string ); + bool setString( String&& string ); void setFont( Font* font ); diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp index 9ae9237d8..2747e4d12 100644 --- a/src/eepp/graphics/text.cpp +++ b/src/eepp/graphics/text.cpp @@ -468,25 +468,31 @@ void Text::onNewString() { } } -void Text::setString( const String::View& string ) { +bool Text::setString( const String::View& string ) { if ( mString.view() != string ) { mString = string; onNewString(); + return true; } + return false; } -void Text::setString( const String& string ) { +bool Text::setString( const String& string ) { if ( mString != string ) { mString = string; onNewString(); + return true; } + return false; } -void Text::setString( String&& string ) { +bool Text::setString( String&& string ) { if ( mString != string ) { mString = std::move( string ); onNewString(); + return true; } + return false; } void Text::setFont( Font* font ) { diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp index 7d54b61d5..2181a6b65 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include using namespace EE::Graphics; @@ -481,22 +482,30 @@ void AutoCompletePlugin::pickSuggestion( UICodeEditor* editor ) { PluginRequestHandle AutoCompletePlugin::processCodeCompletion( const LSPCompletionList& completion ) { SymbolsList suggestions; - for ( const auto& item : completion.items ) { + // FIX: Find a way of passing some messages as non-const and allow to move them. + // Creating a copy of each element is unnecessary and expensive, this time we are going to + // hack it and remove the constness of the suggestions to be able to move all its internal + // values + LSPCompletionList& wcompletion = const_cast( completion ); + for ( auto& item : wcompletion.items ) { if ( !item.textEdit.text.empty() ) { - suggestions.push_back( { item.kind, item.insertText, item.detail, item.sortText, - item.textEdit.range, item.textEdit.text, - item.documentation } ); + suggestions.push_back( { item.kind, std::move( item.insertText ), + std::move( item.detail ), std::move( item.sortText ), + item.textEdit.range, std::move( item.textEdit.text ), + std::move( item.documentation ) } ); } else if ( !item.insertText.empty() ) { - suggestions.push_back( { item.kind, item.insertText, item.detail, item.sortText, - item.textEdit.range, item.insertText, item.documentation } ); + suggestions.push_back( { item.kind, std::move( item.insertText ), + std::move( item.detail ), std::move( item.sortText ), + item.textEdit.range, std::string{ item.insertText }, + std::move( item.documentation ) } ); } else { suggestions.push_back( { item.kind, - item.filterText, - item.detail, - item.sortText, + std::move( item.filterText ), + std::move( item.detail ), + std::move( item.sortText ), {}, "", - item.documentation } ); + std::move( item.documentation ) } ); } } if ( suggestions.empty() || !mSuggestionsEditor ) @@ -786,6 +795,8 @@ void AutoCompletePlugin::postDraw( UICodeEditor* editor, const Vector2f& startSc primitives.drawRoundedRectangle( boxRect, 0.f, Vector2f::One, 6 ); for ( size_t i = mSuggestionsStartIndex; i < maxIndex; i++ ) { + const auto& suggestion = suggestions[i]; + if ( mSuggestionIndex == (int)i ) { primitives.setColor( Color( selectedStyle.background ).blendAlpha( editor->getAlpha() ) ); @@ -798,19 +809,18 @@ void AutoCompletePlugin::postDraw( UICodeEditor* editor, const Vector2f& startSc text.setFillColor( mSuggestionIndex == (int)i ? selectedStyle.color : normalStyle.color ); text.setStyle( mSuggestionIndex == (int)i ? selectedStyle.style : normalStyle.style ); - auto nlPos = suggestions[i].text.find_first_of( '\n' ); + auto nlPos = suggestion.text.find_first_of( '\n' ); if ( nlPos == std::string::npos ) { - text.setString( suggestions[i].text ); + text.setString( suggestion.text ); } else { - text.setString( suggestions[i].text.substr( 0, nlPos ) ); + text.setString( suggestion.text.substr( 0, nlPos ) ); } text.draw( cursorPos.x + iconSpace.getWidth() + mBoxPadding.Left, cursorPos.y + mRowHeight * count + mBoxPadding.Top ); Drawable* icon = editor->getUISceneNode()->findIconDrawable( - LSPCompletionItemHelper::toIconString( suggestions[i].kind ), - PixelDensity::dpToPxI( 12 ) ); + LSPCompletionItemHelper::toIconString( suggestion.kind ), PixelDensity::dpToPxI( 12 ) ); if ( icon ) { Vector2f padding( @@ -819,19 +829,34 @@ void AutoCompletePlugin::postDraw( UICodeEditor* editor, const Vector2f& startSc icon->draw( { cursorPos.x + padding.x, cursorPos.y + mRowHeight * count + padding.y } ); } - if ( mSuggestionIndex == (int)i && !suggestions[i].documentation.value.empty() ) { - Text text( "", editor->getFont(), editor->getFontSize() ); - text.setFillColor( normalStyle.color ); - text.setStyle( normalStyle.style ); - text.setString( suggestions[i].documentation.value ); + if ( mSuggestionIndex == (int)i && !suggestion.documentation.value.empty() ) { + mSuggestionDoc.setFont( editor->getFont() ); + mSuggestionDoc.setFontSize( editor->getFontSize() ); + mSuggestionDoc.setFillColor( normalStyle.color ); + mSuggestionDoc.setStyle( normalStyle.style ); + bool changed = mSuggestionDoc.setString( suggestion.documentation.value ); + Vector2f boxPos = { cursorPos.x + mBoxRect.getWidth(), cursorPos.y + mRowHeight * count }; - Sizef boxSize = { text.getTextWidth() + mBoxPadding.Left + mBoxPadding.Right, - text.getTextHeight() + mBoxPadding.Top + mBoxPadding.Bottom }; + Sizef boxSize = { mSuggestionDoc.getTextWidth() + mBoxPadding.Left + mBoxPadding.Right, + mSuggestionDoc.getTextHeight() + mBoxPadding.Top + + mBoxPadding.Bottom }; primitives.setColor( Color( selectedStyle.background ).blendAlpha( editor->getAlpha() ) ); primitives.drawRoundedRectangle( { boxPos, boxSize }, 0.f, Vector2f::One, 6 ); - text.draw( boxPos.x + mBoxPadding.Left, boxPos.y + mBoxPadding.Top ); + + if ( changed ) { + bool forceHTML = String::startsWith( suggestion.detail, "Emmet" ); + if ( suggestion.documentation.kind == LSPMarkupKind::MarkDown || forceHTML ) { + const auto& syntaxDef = forceHTML ? + SyntaxDefinitionManager::instance()->getByLSPName( "html" ) : + SyntaxDefinitionManager::instance()->getByLSPName( "markdown" ); + SyntaxTokenizer::tokenizeText( syntaxDef, editor->getColorScheme(), + mSuggestionDoc, 0, 0xFFFFFFFF, true, "\n\t " ); + } + } + + mSuggestionDoc.draw( boxPos.x + mBoxPadding.Left, boxPos.y + mBoxPadding.Top ); } count++; } diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp index 4ece37d46..8c566bdac 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp @@ -37,16 +37,15 @@ class AutoCompletePlugin : public Plugin { Suggestion( const std::string& text ) : text( text ), sortText( text ) {} - Suggestion( const LSPCompletionItemKind& kind, const std::string& text, - const std::string& detail, const std::string& sortText, - const TextRange& range = {}, const std::string insertText = "", - LSPMarkupContent doc = {} ) : + Suggestion( LSPCompletionItemKind kind, std::string&& text, std::string&& detail, + std::string&& sortText, const TextRange& range, std::string&& insertText, + LSPMarkupContent&& doc ) : kind( kind ), - text( text ), - detail( detail ), - sortText( sortText.empty() ? text : sortText ), + text( std::move( text ) ), + detail( std::move( detail ) ), + sortText( sortText.empty() ? std::string{ text } : std::move( sortText ) ), range( range ), - insertText( insertText ), + insertText( std::move( insertText ) ), documentation( doc ){}; bool operator<( const Suggestion& other ) const { return getCmpStr() < other.getCmpStr(); } @@ -149,6 +148,7 @@ class AutoCompletePlugin : public Plugin { std::unordered_map> mHandles; std::unordered_map> mDocsUpdating; Mutex mDocsUpdatingMutex; + Text mSuggestionDoc; Float mRowHeight{ 0 }; Rectf mBoxRect;