From c2697bdce94e63e600214cfe488a62210f597cea Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 24 Jul 2012 10:37:33 +0100 Subject: [PATCH] Code editor fix for long lines. --- .../code_editor/juce_CodeEditorComponent.cpp | 67 ++++++++++++------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp b/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp index 34aea9c459..1be945be50 100644 --- a/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp +++ b/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp @@ -41,7 +41,8 @@ public: if (tokeniser == nullptr) { - newTokens.add (SyntaxToken (document.getLine (lineNum), -1)); + const String line (document.getLine (lineNum)); + addToken (newTokens, line, line.length(), -1); } else if (lineNum < document.getNumLines()) { @@ -81,22 +82,29 @@ public: } void draw (CodeEditorComponent& owner, Graphics& g, const Font& font, - float x, const float rightEdge, const int y, const int baselineOffset, const int lineHeight, + const float leftClip, const float rightClip, + const float xOffset, const int y, const int baselineOffset, + const int lineHeight, const float charWidth, const Colour& highlightColour) const { if (highlightColumnStart < highlightColumnEnd) { g.setColour (highlightColour); - g.fillRect (roundToInt (x + highlightColumnStart * owner.getCharWidth()), y, + g.fillRect (roundToInt (xOffset + highlightColumnStart * owner.getCharWidth()), y, roundToInt ((highlightColumnEnd - highlightColumnStart) * owner.getCharWidth()), lineHeight); } const float baselineY = (float) (y + baselineOffset); Colour lastColour (0x00000001); GlyphArrangement ga; + int column = 0; for (int i = 0; i < tokens.size(); ++i) { + const float tokenX = xOffset + column * charWidth; + if (tokenX > rightClip) + break; + SyntaxToken& token = tokens.getReference(i); const Colour newColour (owner.getColourForTokenType (token.tokenType)); @@ -109,18 +117,11 @@ public: g.setColour (newColour); } - ga.addCurtailedLineOfText (font, token.text, x, baselineY, rightEdge - x, false); - - if (i < tokens.size() - 1) - { - if (token.width < 0) - token.width = font.getStringWidthFloat (token.text); - - x += token.width; + column += token.length; - if (x > rightEdge) - break; - } + if (xOffset + column * charWidth >= leftClip) + ga.addCurtailedLineOfText (font, token.text, tokenX, baselineY, + (rightClip - tokenX) + charWidth, false); } ga.draw (g); @@ -129,19 +130,21 @@ public: private: struct SyntaxToken { - SyntaxToken (const String& t, const int type) noexcept - : text (t), tokenType (type), width (-1.0f) + SyntaxToken (const String& t, const int len, const int type) noexcept + : text (t), length (len), tokenType (type) { } bool operator== (const SyntaxToken& other) const noexcept { - return tokenType == other.tokenType && text == other.text; + return tokenType == other.tokenType + && length == other.length + && text == other.text; } String text; + int length; int tokenType; - float width; }; Array tokens; @@ -169,8 +172,9 @@ private: if (tokenEnd > 0) { tokenStart -= startPosition; - newTokens.add (SyntaxToken (lineText.substring (jmax (0, tokenStart), tokenEnd), - tokenType)); + const int start = jmax (0, tokenStart); + addToken (newTokens, lineText.substring (start, tokenEnd), + tokenEnd - start, tokenType); if (tokenEnd >= lineLength) break; @@ -219,6 +223,21 @@ private: return col; } + + static void addToken (Array& dest, const String& text, + const int length, const int type) + { + if (length > 1000) + { + // subdivide very long tokens to avoid unwieldy glyph sequences + addToken (dest, text.substring (0, length / 2), length / 2, type); + addToken (dest, text.substring (length / 2), length - length / 2, type); + } + else + { + dest.add (SyntaxToken (text, length, type)); + } + } }; namespace CodeEditorHelpers @@ -451,11 +470,13 @@ void CodeEditorComponent::paint (Graphics& g) const int firstLineToDraw = jmax (0, clip.getY() / lineHeight); const int lastLineToDraw = jmin (lines.size(), clip.getBottom() / lineHeight + 1); const float x = (float) (gutter - xOffset * charWidth); - const float rightEdge = (float) getWidth(); + const float leftClip = (float) clip.getX(); + const float rightClip = (float) clip.getRight(); for (int i = firstLineToDraw; i < lastLineToDraw; ++i) - lines.getUnchecked(i)->draw (*this, g, font, x, rightEdge, lineHeight * i, - baselineOffset, lineHeight, highlightColour); + lines.getUnchecked(i)->draw (*this, g, font, leftClip, rightClip, + x, lineHeight * i, baselineOffset, + lineHeight, charWidth, highlightColour); } void CodeEditorComponent::setScrollbarThickness (const int thickness)