diff --git a/docs/articles/cssspecification.md b/docs/articles/cssspecification.md index 7761b05ce..55e863eba 100644 --- a/docs/articles/cssspecification.md +++ b/docs/articles/cssspecification.md @@ -542,6 +542,21 @@ Custom cursors not yet supported (but supported by the engine, only not implemen --- +### disable-editor-flags + +Allows disabling specific behavior flags for the code editor component. +Flags set here take precedence over [enable-editor-flags](#enable-editor-flags). +Multiple flags are separated by `|`. + +* Applicable to: Any element child of a EE::UI::UICodeEditor (CodeEditor) +* Data Type: [string-list](#string-list-data-type) +* Value List: + * All flags listed in [enable-editor-flags](#enable-editor-flags) can be used here to disable their respective features. + * `editorfeatures`: Macro Flag - Disables line numbers, whitespace display, folding regions, current line highlight, matching bracket highlight, selection match highlight, color picker, minimap, and find/replace. Resets line breaking and forces the editor to use the default style. +* Default value: _No value_ + +--- + ### display-percent Enables/disables displaying the percentage of progress in the progress bar. @@ -583,6 +598,41 @@ Sets if the element is enabled --- +### enable-editor-flags + +Allows enabling specific behavior flags for the code editor component. Multiple flags can be specified, separated by `|`. + +* Applicable to: Any element child of a EE::UI::UICodeEditor (CodeEditor) +* Data Type: [string-list](#string-list-data-type) +* Value List: + * `linenumber`: Displays line numbers in the gutter. + * `foldingregion`: Shows code folding regions for collapsing/expanding blocks. + * `whitespaces`: Renders whitespace characters (spaces, tabs) as visible symbols. + * `lineendings`: Displays line ending characters (e.g., CR, LF). + * `highlightcurrentline`: Highlights the background of the current line containing the cursor. + * `highlightmatchingbracket`: Highlights the bracket matching the one under the cursor. + * `highlightselectionmatch`: Highlights all occurrences of the selected text in the document. + * `colorpickeronselection`: Opens a color picker dialog when a color value is selected. + * `verticalscrollbar`: Enables the vertical scrollbar for scrolling through content. + * `horizontalscrollbar`: Enables the horizontal scrollbar for scrolling through content. + * `colorpreview`: Shows a color preview on mouse hover. + * `interactivelinks`: Enables interaction with clickable hyperlinks within the editor. + * `displayloader`: Displays a loading indicator while the document is loading. + * `defaultcontextmenu`: Provides a default context menu with standard editing options. + * `minimap`: Shows a minimap (overview) of the document on the right side. + * `autoclosexmltags`: Automatically inserts closing tags in XML/HTML documents. + * `findreplace`: Enables the find and replace functionality. + * `showindentationguides`: Displays vertical guides to indicate indentation levels. + * `linesrelativeposition`: Shows the relative position of lines (e.g., in a diff view). + * `lockedicon`: Displays a lock icon when the editor is in a locked state. + * `foldsalwaysvisible`: Keeps fold markers visible even when not hovered. + * `foldsvisible`: Makes folded code regions visible. + * `flashcursor`: Enables a flashing animation for the text cursor. + * `defaultstyle`: Applies the default styling and theme to the editor. +* Default value: _No value_ + +--- + ### font-family Read [font-family](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family) documentation. @@ -1052,6 +1102,33 @@ Sets a extra line spacing to the line box. --- +### line-wrap-mode + +Specifies the line wrap mode of the element. + +* Applicable to: Any element child of a EE::UI::UICodeEditor (CodeEditor) +* Data Type: [string-list](#string-list-data-type) +* Value List: + * `word`: Wraps against words. + * `letter`: Wraps against letters. + * `nowrap`: Does not wrap. +* Default value: `nowrap` + +--- + +### line-wrap-type + +Specifies if line must wrap against its viewport or the defined line breaking column. + +* Applicable to: Any element child of a EE::UI::UICodeEditor (CodeEditor) +* Data Type: [string-list](#string-list-data-type) +* Value List: + * `viewport`: Wrap against the element viewport. + * `line_breaking_column`: Wraps against the line breaking column. +* Default value: `viewport` + +--- + ### locked Enable or disable editing on code editor elements. @@ -1462,6 +1539,22 @@ Sets the vertical separation between each element in the grid layout. --- +### row-valign + +Sets the vertical alignment of the elements in a stack layout. Elements in the same row will align +based on the maximum element height in that row. + +* Applicable to: EE::UI::UIStackLayout (StackLayout) +* Data Type: [string-list](#string-list-data-type) + +* Value List: + * `top`: Aligns to the top of the row. + * `bottom`: Aligns to the bottom of the row. + * `center`: Aligns to the center of the row. +* Default value: `bottom` + +--- + ### row-weight Sets the percentage height of the child elements of a grid layout. diff --git a/include/eepp/graphics/text.hpp b/include/eepp/graphics/text.hpp index b51be3348..bc5350cf2 100644 --- a/include/eepp/graphics/text.hpp +++ b/include/eepp/graphics/text.hpp @@ -8,6 +8,15 @@ namespace EE { namespace Graphics { +enum class CharacterAlignment : Uint32 { Left = 0, Center = 1, Right = 2 }; + +struct WhitespaceDisplayConfig { + String::StringBaseType spaceDisplayCharacter{ 0 }; + String::StringBaseType tabDisplayCharacter{ 0 }; + CharacterAlignment tabAlign{ CharacterAlignment::Center }; + Color color; +}; + class EE_API Text { public: static bool TextShaperEnabled; @@ -48,21 +57,25 @@ class EE_API Text { const Color& outlineColor = Color::Black, const Color& shadowColor = Color::Black, const Vector2f& shadowOffset = { 1, 1 }, const Uint32& tabWidth = 4, - Uint32 textDrawHints = 0 ); + Uint32 textDrawHints = 0, + const WhitespaceDisplayConfig& whitespaceDisplayConfig = {} ); static Sizef draw( const String& string, const Vector2f& pos, const FontStyleConfig& config, - const Uint32& tabWidth = 4, Uint32 textDrawHints = 0 ); + const Uint32& tabWidth = 4, Uint32 textDrawHints = 0, + const WhitespaceDisplayConfig& whitespaceDisplayConfig = {} ); static Sizef draw( const String::View& string, const Vector2f& pos, Font* font, Float fontSize, const Color& fontColor, Uint32 style = 0, Float outlineThickness = 0.f, const Color& outlineColor = Color::Black, const Color& shadowColor = Color::Black, const Vector2f& shadowOffset = { 1, 1 }, const Uint32& tabWidth = 4, - Uint32 textDrawHints = 0 ); + Uint32 textDrawHints = 0, + const WhitespaceDisplayConfig& whitespaceDisplayConfig = {} ); static Sizef draw( const String::View& string, const Vector2f& pos, const FontStyleConfig& config, const Uint32& tabWidth = 4, - Uint32 textDrawHints = 0 ); + Uint32 textDrawHints = 0, + const WhitespaceDisplayConfig& whitespaceDisplayConfig = {} ); static void drawUnderline( const Vector2f& pos, Float width, Font* font, Float fontSize, const Color& fontColor, const Uint32& style, Float outlineThickness, @@ -315,16 +328,17 @@ class EE_API Text { const Float& outlineThickness = 0.f ); template - static Sizef draw( const StringType& string, const Vector2f& pos, Font* font, Float fontSize, - const Color& fontColor, Uint32 style = 0, Float outlineThickness = 0.f, - const Color& outlineColor = Color::Black, - const Color& shadowColor = Color::Black, - const Vector2f& shadowOffset = { 1, 1 }, const Uint32& tabWidth = 4, - Uint32 textDrawHints = 0 ); + static Sizef + draw( const StringType& string, const Vector2f& pos, Font* font, Float fontSize, + const Color& fontColor, Uint32 style = 0, Float outlineThickness = 0.f, + const Color& outlineColor = Color::Black, const Color& shadowColor = Color::Black, + const Vector2f& shadowOffset = { 1, 1 }, const Uint32& tabWidth = 4, + Uint32 textDrawHints = 0, const WhitespaceDisplayConfig& whitespaceDisplayConfig = {} ); template static Sizef draw( const StringType& string, const Vector2f& pos, const FontStyleConfig& config, - const Uint32& tabWidth = 4, Uint32 textDrawHints = 0 ); + const Uint32& tabWidth = 4, Uint32 textDrawHints = 0, + const WhitespaceDisplayConfig& whitespaceDisplayConfig = {} ); template static std::size_t findLastCharPosWithinLength( Font* font, const Uint32& fontSize, diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index d8f45b13d..1e6ead18b 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -33,8 +33,6 @@ class UILoader; class UIPopUpMenu; class UIMenuItem; -enum class CharacterAlignment : Uint32 { Left = 0, Center = 1, Right = 2 }; - using DocumentLineRange = std::pair; using DocumentViewLineRange = std::pair; diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp index 4f296e219..206a4bff7 100644 --- a/src/eepp/graphics/text.cpp +++ b/src/eepp/graphics/text.cpp @@ -241,27 +241,34 @@ Float Text::getTextWidth( const String::View& string, const FontStyleConfig& con Sizef Text::draw( const String& string, const Vector2f& pos, Font* font, Float fontSize, const Color& fontColor, Uint32 style, Float outlineThickness, const Color& outlineColor, const Color& shadowColor, const Vector2f& shadowOffset, - const Uint32& tabWidth, Uint32 textDrawHints ) { + const Uint32& tabWidth, Uint32 textDrawHints, + const WhitespaceDisplayConfig& whitespaceDisplayConfig ) { return draw( string, pos, font, fontSize, fontColor, style, outlineThickness, - outlineColor, shadowColor, shadowOffset, tabWidth, textDrawHints ); + outlineColor, shadowColor, shadowOffset, tabWidth, textDrawHints, + whitespaceDisplayConfig ); } Sizef Text::draw( const String& string, const Vector2f& pos, const FontStyleConfig& config, - const Uint32& tabWidth, Uint32 textDrawHints ) { - return draw( string, pos, config, tabWidth, textDrawHints ); + const Uint32& tabWidth, Uint32 textDrawHints, + const WhitespaceDisplayConfig& whitespaceDisplayConfig ) { + return draw( string, pos, config, tabWidth, textDrawHints, whitespaceDisplayConfig ); } Sizef Text::draw( const String::View& string, const Vector2f& pos, Font* font, Float fontSize, const Color& fontColor, Uint32 style, Float outlineThickness, const Color& outlineColor, const Color& shadowColor, const Vector2f& shadowOffset, - const Uint32& tabWidth, Uint32 textDrawHints ) { + const Uint32& tabWidth, Uint32 textDrawHints, + const WhitespaceDisplayConfig& whitespaceDisplayConfig ) { return draw( string, pos, font, fontSize, fontColor, style, outlineThickness, - outlineColor, shadowColor, shadowOffset, tabWidth, textDrawHints ); + outlineColor, shadowColor, shadowOffset, tabWidth, textDrawHints, + whitespaceDisplayConfig ); } Sizef Text::draw( const String::View& string, const Vector2f& pos, const FontStyleConfig& config, - const Uint32& tabWidth, Uint32 textDrawHints ) { - return draw( string, pos, config, tabWidth, textDrawHints ); + const Uint32& tabWidth, Uint32 textDrawHints, + const WhitespaceDisplayConfig& whitespaceDisplayConfig ) { + return draw( string, pos, config, tabWidth, textDrawHints, + whitespaceDisplayConfig ); } Text* Text::New() { @@ -376,7 +383,8 @@ template Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Float fontSize, const Color& fontColor, Uint32 style, Float outlineThickness, const Color& outlineColor, const Color& shadowColor, const Vector2f& shadowOffset, - const Uint32& tabWidth, Uint32 textDrawHints ) { + const Uint32& tabWidth, Uint32 textDrawHints, + const WhitespaceDisplayConfig& whitespaceDisplayConfig ) { Vector2f cpos{ pos }; String::StringBaseType ch; String::StringBaseType prevChar = 0; @@ -398,94 +406,124 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo size_t ssize = string.size(); BatchRenderer* BR = GlobalBatchRenderer::instance(); Texture* fontTexture = font->getTexture( fontSize ); + Float tabAlign = 0; + GlyphDrawable* spaceGlyph = nullptr; + GlyphDrawable* tabGlyph = nullptr; + Float hspace = font->getGlyph( ' ', fontSize, isBold, isItalic ).advance; + if ( whitespaceDisplayConfig.tabDisplayCharacter ) { + tabGlyph = font->getGlyphDrawable( whitespaceDisplayConfig.tabDisplayCharacter, fontSize ); + switch ( whitespaceDisplayConfig.tabAlign ) { + case CharacterAlignment::Center: + tabAlign = ( ( tabWidth * hspace ) - tabGlyph->getPixelsSize().getWidth() ) * 0.5f; + break; + case CharacterAlignment::Right: + tabAlign = ( tabWidth * hspace ) - tabGlyph->getPixelsSize().getWidth(); + break; + case CharacterAlignment::Left: + break; + } + } + BR->setBlendMode( BlendMode::Alpha() ); BR->quadsBegin(); BR->setTexture( fontTexture, fontTexture->getCoordinateType() ); #ifdef EE_TEXT_SHAPER_ENABLED if ( TextShaperEnabled && font->getType() == FontType::TTF ) { - Float hspace = font->getGlyph( ' ', fontSize, isBold, isItalic ).advance; FontTrueType* rFont = static_cast( font ); - shapeAndRun( string, rFont, fontSize, style, outlineThickness, - [&]( hb_glyph_info_t* glyphInfo, hb_glyph_position_t*, Uint32 glyphCount, - const hb_segment_properties_t&, TextShapeRun& run ) { - FontTrueType* font = run.font(); - Uint32 prevGlyphIndex = 0; - Uint32 cluster = 0; - for ( std::size_t i = 0; i < glyphCount; ++i ) { - hb_glyph_info_t curGlyph = glyphInfo[i]; - cluster = curGlyph.cluster; - ch = string[cluster]; - if ( ch == '\t' ) { - width += hspace * tabWidth; - cpos.x += hspace * tabWidth; - } else { - if ( style & Text::Shadow ) { - auto* gds = font->getGlyphDrawableFromGlyphIndex( - curGlyph.codepoint, fontSize, isBold, isItalic, - outlineThickness, rFont->getPage( fontSize ) ); - if ( gds ) - drawGlyph( BR, gds, cpos, shadowColor, isItalic ); - } + shapeAndRun( + string, rFont, fontSize, style, outlineThickness, + [&]( hb_glyph_info_t* glyphInfo, hb_glyph_position_t*, Uint32 glyphCount, + const hb_segment_properties_t&, TextShapeRun& run ) { + FontTrueType* font = run.font(); + Uint32 prevGlyphIndex = 0; + Uint32 cluster = 0; + for ( std::size_t i = 0; i < glyphCount; ++i ) { + hb_glyph_info_t curGlyph = glyphInfo[i]; + cluster = curGlyph.cluster; + ch = string[cluster]; + if ( ch == '\t' ) { + if ( tabGlyph ) { + drawGlyph( BR, tabGlyph, { cpos.x + tabAlign, cpos.y }, + whitespaceDisplayConfig.color, isItalic ); + } + width += hspace * tabWidth; + cpos.x += hspace * tabWidth; + } else { + if ( style & Text::Shadow ) { + auto* gds = font->getGlyphDrawableFromGlyphIndex( + curGlyph.codepoint, fontSize, isBold, isItalic, outlineThickness, + rFont->getPage( fontSize ) ); + if ( gds ) + drawGlyph( BR, gds, cpos, shadowColor, isItalic ); + } - if ( outlineThickness != 0.f ) { - auto* gdo = font->getGlyphDrawableFromGlyphIndex( - curGlyph.codepoint, fontSize, isBold, isItalic, - outlineThickness, rFont->getPage( fontSize ) ); - if ( gdo ) - drawGlyph( BR, gdo, cpos, outlineColor, isItalic ); - } + if ( outlineThickness != 0.f ) { + auto* gdo = font->getGlyphDrawableFromGlyphIndex( + curGlyph.codepoint, fontSize, isBold, isItalic, outlineThickness, + rFont->getPage( fontSize ) ); + if ( gdo ) + drawGlyph( BR, gdo, cpos, outlineColor, isItalic ); + } - auto* gd = font->getGlyphDrawableFromGlyphIndex( - curGlyph.codepoint, fontSize, isBold, isItalic, 0, - rFont->getPage( fontSize ) ); - if ( gd ) { - if ( !isMonospace ) { - kerning = font->getKerningFromGlyphIndex( - prevGlyphIndex, curGlyph.codepoint, fontSize, isBold, - isItalic, outlineThickness ); - cpos.x += kerning; - width += kerning; - } + auto* gd = font->getGlyphDrawableFromGlyphIndex( + curGlyph.codepoint, fontSize, isBold, isItalic, 0, + rFont->getPage( fontSize ) ); + if ( gd ) { + if ( !isMonospace ) { + kerning = font->getKerningFromGlyphIndex( + prevGlyphIndex, curGlyph.codepoint, fontSize, isBold, isItalic, + outlineThickness ); + cpos.x += kerning; + width += kerning; + } - drawGlyph( BR, gd, cpos, - fallbacksToColorEmoji && - Font::isEmojiCodePoint( ch ) - ? Color::White - : fontColor, - isItalic ); + drawGlyph( BR, gd, cpos, + fallbacksToColorEmoji && Font::isEmojiCodePoint( ch ) + ? Color::White + : fontColor, + isItalic ); - Float advance = font->isColorEmojiFont() && ' ' != ch - ? gd->getPixelsSize().getWidth() - : gd->getAdvance(); - cpos.x += advance; - width += advance; - } - } + if ( ch == ' ' && whitespaceDisplayConfig.spaceDisplayCharacter ) { + if ( spaceGlyph == nullptr ) { + spaceGlyph = font->getGlyphDrawable( + whitespaceDisplayConfig.spaceDisplayCharacter, fontSize ); + } + drawGlyph( BR, spaceGlyph, cpos, whitespaceDisplayConfig.color, + isItalic ); + } - prevGlyphIndex = curGlyph.codepoint; - } + Float advance = font->isColorEmojiFont() && ' ' != ch + ? gd->getPixelsSize().getWidth() + : gd->getAdvance(); + cpos.x += advance; + width += advance; + } + } - if ( run.runIsNewLine() ) { - if ( style & Text::Underlined ) { - _drawUnderline( font, fontSize, fontColor, cpos, style, BR, - outlineThickness, pos, width, shadowColor, - shadowOffset, outlineColor ); - } - if ( style & Text::StrikeThrough ) { - _drawStrikeThrough( font, fontSize, fontColor, cpos, style, BR, - outlineThickness, pos, width, shadowColor, - shadowOffset, outlineColor ); - } - size.x = eemax( width, size.x ); - width = 0; - cpos.x = pos.x; - cpos.y += height; - if ( cluster != ssize - 1 ) - size.y += height; - } - return true; - } ); + prevGlyphIndex = curGlyph.codepoint; + } + + if ( run.runIsNewLine() ) { + if ( style & Text::Underlined ) { + _drawUnderline( font, fontSize, fontColor, cpos, style, BR, + outlineThickness, pos, width, shadowColor, shadowOffset, + outlineColor ); + } + if ( style & Text::StrikeThrough ) { + _drawStrikeThrough( font, fontSize, fontColor, cpos, style, BR, + outlineThickness, pos, width, shadowColor, shadowOffset, + outlineColor ); + } + size.x = eemax( width, size.x ); + width = 0; + cpos.x = pos.x; + cpos.y += height; + if ( cluster != ssize - 1 ) + size.y += height; + } + return true; + } ); if ( ( style & Text::Underlined ) && width != 0 ) { _drawUnderline( font, fontSize, fontColor, cpos, style, BR, outlineThickness, pos, @@ -512,17 +550,26 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo case '\r': continue; case '\t': { - Float advance = - font->getGlyph( ' ', fontSize, isBold, isItalic ).advance * tabWidth; + Float advance = hspace * tabWidth; + if ( tabGlyph ) { + drawGlyph( BR, tabGlyph, { cpos.x + tabAlign, cpos.y }, + whitespaceDisplayConfig.color, isItalic ); + } width += advance; cpos.x += advance; prevChar = ch; continue; } case ' ': { - Float advance = font->getGlyph( ' ', fontSize, isBold, isItalic ).advance; - width += advance; - cpos.x += advance; + if ( whitespaceDisplayConfig.spaceDisplayCharacter ) { + if ( spaceGlyph == nullptr ) { + spaceGlyph = font->getGlyphDrawable( + whitespaceDisplayConfig.spaceDisplayCharacter, fontSize ); + } + drawGlyph( BR, spaceGlyph, cpos, whitespaceDisplayConfig.color, isItalic ); + } + width += hspace; + cpos.x += hspace; prevChar = ch; continue; } @@ -598,10 +645,12 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo template Sizef Text::draw( const StringType& string, const Vector2f& pos, const FontStyleConfig& config, - const Uint32& tabWidth, Uint32 textDrawHints ) { + const Uint32& tabWidth, Uint32 textDrawHints, + const WhitespaceDisplayConfig& whitespaceDisplayConfig ) { return draw( string, pos, config.Font, config.CharacterSize, config.FontColor, config.Style, config.OutlineThickness, config.OutlineColor, - config.ShadowColor, config.ShadowOffset, tabWidth, textDrawHints ); + config.ShadowColor, config.ShadowOffset, tabWidth, textDrawHints, + whitespaceDisplayConfig ); } template diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 78e809bc0..3184e93f4 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -326,11 +326,6 @@ void UICodeEditor::draw() { drawIndentationGuides( lineRange, startScroll, lineHeight ); } - // Draw tab marker - if ( mShowWhitespaces ) { - drawWhitespaces( lineRange, startScroll, lineHeight, visibleLineRange ); - } - if ( mShowLineEndings ) { drawLineEndings( lineRange, startScroll, lineHeight ); } @@ -1155,6 +1150,8 @@ void UICodeEditor::setCodeEditorFlags( std::string flags, bool enable ) { mEnableColorPickerOnSelection = enable; } else if ( "verticalscrollbar" == flag ) { setVerticalScrollBarEnabled( enable ); + } else if ( "horizontalscrollbar" == flag ) { + setHorizontalScrollBarEnabled( enable ); } else if ( "colorpreview" == flag ) { mColorPreview = enable; } else if ( "interactivelinks" == flag ) { @@ -1953,7 +1950,7 @@ Float UICodeEditor::getLineWidth( const Int64& docLine ) { auto& line = mDoc->line( docLine ).getText(); Float width = 0; - if ( !isMonospaceLine ) { + if ( isNotMonospace() ) { auto& line = mDoc->line( docLine ); auto found = mLinesWidthCache.find( docLine ); if ( found != mLinesWidthCache.end() && line.getHash() == found->second.first ) @@ -1969,14 +1966,14 @@ Float UICodeEditor::getLineWidth( const Int64& docLine ) { width = eemax( width, curWidth ); } - if ( !isMonospaceLine ) { + if ( isNotMonospace() ) { mLinesWidthCache[docLine] = { line.getHash(), width }; } return width; } - if ( !isMonospaceLine ) { + if ( isNotMonospace() ) { auto& line = mDoc->line( docLine ); auto found = mLinesWidthCache.find( docLine ); if ( found != mLinesWidthCache.end() && line.getHash() == found->second.first ) @@ -2008,8 +2005,8 @@ void UICodeEditor::updateScrollBar() { Float viewPortWidth = getViewportWidth(); mHScrollBar->setPageStep( viewPortWidth / mLongestLineWidth ); mHScrollBar->setClickStep( 0.2f ); - bool showHScroll = mLongestLineWidth > viewPortWidth && - !( mDocView.isWrapEnabled() && mLongestLineWidthDirty ); + bool showHScroll = mLongestLineWidth > viewPortWidth && !mDocView.isWrapEnabled() && + !mLongestLineWidthDirty; mHScrollBar->setEnabled( showHScroll ); mHScrollBar->setVisible( showHScroll ); } @@ -3773,6 +3770,10 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo ttf->setEnableFallbackFont( false ); ttf->setEnableEmojiFallback( false ); } + WhitespaceDisplayConfig whitespaceDisplayConfig = + mShowWhitespaces ? WhitespaceDisplayConfig{ L'ยท', mTabIndentCharacter, mTabIndentAlignment, + Color( mWhitespaceColor ).blendAlpha( mAlpha ) } + : WhitespaceDisplayConfig{}; String::View buff; Sizef size; @@ -3854,9 +3855,10 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo } } - position.x += Text::draw( text, { position.x, position.y + lineOffset }, - fontStyle, mTabWidth, drawHints ) - .getWidth(); + position.x += + Text::draw( text, { position.x, position.y + lineOffset }, fontStyle, + mTabWidth, drawHints, whitespaceDisplayConfig ) + .getWidth(); } pos += text.size(); @@ -3925,18 +3927,18 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo size = Text::draw( text.substr( start, end ), { position.x + start * getGlyphWidth(), position.y + lineOffset }, - fontStyle, mTabWidth, drawHints ); + fontStyle, mTabWidth, drawHints, whitespaceDisplayConfig ); if ( minimumCharsToCoverScreen == end ) break; } } else { size = Text::draw( text.substr( 0, eemin( curCharsWidth, maxWidth ) ), { position.x, position.y + lineOffset }, fontStyle, - mTabWidth, drawHints ); + mTabWidth, drawHints, whitespaceDisplayConfig ); } } else { size = Text::draw( text, { position.x, position.y + lineOffset }, fontStyle, - mTabWidth, drawHints ); + mTabWidth, drawHints, whitespaceDisplayConfig ); } if ( !isMonospace ) diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp index 96a93b627..b75361fad 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp @@ -1427,6 +1427,12 @@ void DebuggerPlugin::drawLineNumbersBefore( UICodeEditor* editor, Float lineOffset = editor->getLineOffset(); Float offset = editor->getGutterLocalStartOffset( this ); + p.setColor( Color( editor->getLineNumberBackgroundColor() ).blendAlpha( editor->getAlpha() ) ); + p.drawRectangle( Rectf( { screenStart.x - editor->getPluginsGutterSpace() + offset, + screenStart.y + editor->getPluginsTopSpace() }, + Sizef( gutterSpace, editor->getPixelsSize().getHeight() - + editor->getPluginsTopSpace() ) ) ); + if ( editor->getDocument().hasFilepath() ) { auto docIt = mBreakpoints.find( editor->getDocument().getFilePath() ); if ( docIt != mBreakpoints.end() && !docIt->second.empty() ) {