1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-24 01:54:22 +00:00

Fixed a repaint glitch in the CodeEditorComponent, and updated some of its internal code

This commit is contained in:
jules 2017-05-10 11:34:34 +01:00
parent e58bdc9c18
commit e6590cf095
2 changed files with 64 additions and 87 deletions

View file

@ -27,9 +27,7 @@
class CodeEditorComponent::CodeEditorLine
{
public:
CodeEditorLine() noexcept : highlightColumnStart (0), highlightColumnEnd (0)
{
}
CodeEditorLine() noexcept {}
bool update (CodeDocument& codeDoc, int lineNum,
CodeDocument::Iterator& source,
@ -42,7 +40,7 @@ public:
if (tokeniser == nullptr)
{
const String line (codeDoc.getLine (lineNum));
auto line = codeDoc.getLine (lineNum);
addToken (newTokens, line, line.length(), -1);
}
else if (lineNum < codeDoc.getNumLines())
@ -59,7 +57,7 @@ public:
if (selStart.getLineNumber() <= lineNum && selEnd.getLineNumber() >= lineNum)
{
const String line (codeDoc.getLine (lineNum));
auto line = codeDoc.getLine (lineNum);
CodeDocument::Position lineStart (codeDoc, lineNum, 0), lineEnd (codeDoc, lineNum + 1, 0);
newHighlightStart = indexToColumn (jmax (0, selStart.getPosition() - lineStart.getPosition()),
@ -98,18 +96,17 @@ public:
int column = 0;
for (int i = 0; i < tokens.size(); ++i)
for (auto& token : tokens)
{
const float tokenX = x + column * characterWidth;
if (tokenX > rightClip)
break;
const SyntaxToken& token = tokens.getReference(i);
as.append (token.text.initialSectionNotContaining ("\r\n"), fontToUse, owner.getColourForTokenType (token.tokenType));
column += token.length;
}
as.draw (g, Rectangle<float> (x, (float) y, column * characterWidth + 10.0f, (float) lineH));
as.draw (g, { x, (float) y, column * characterWidth + 10.0f, (float) lineH });
}
private:
@ -132,7 +129,7 @@ private:
};
Array<SyntaxToken> tokens;
int highlightColumnStart, highlightColumnEnd;
int highlightColumnStart = 0, highlightColumnEnd = 0;
static void createTokens (int startPosition, const String& lineText,
CodeDocument::Iterator& source,
@ -173,10 +170,9 @@ private:
static void replaceTabsWithSpaces (Array<SyntaxToken>& tokens, const int spacesPerTab)
{
int x = 0;
for (int i = 0; i < tokens.size(); ++i)
{
SyntaxToken& t = tokens.getReference(i);
for (auto& t : tokens)
{
for (;;)
{
const int tabPos = t.text.indexOfChar ('\t');
@ -229,7 +225,7 @@ namespace CodeEditorHelpers
{
static int findFirstNonWhitespaceChar (StringRef line) noexcept
{
String::CharPointerType t (line.text);
auto t = line.text;
int i = 0;
while (! t.isEmpty())
@ -285,7 +281,7 @@ private:
class CodeEditorComponent::GutterComponent : public Component
{
public:
GutterComponent() : firstLine (0), lastNumLines (0) {}
GutterComponent() {}
void paint (Graphics& g) override
{
@ -295,7 +291,7 @@ public:
g.fillAll (editor.findColour (CodeEditorComponent::backgroundColourId)
.overlaidWith (editor.findColour (lineNumberBackgroundId)));
const Rectangle<int> clip (g.getClipBounds());
auto clip = g.getClipBounds();
const int lineH = editor.lineHeight;
const float lineHeightFloat = (float) lineH;
const int firstLineToDraw = jmax (0, clip.getY() / lineH);
@ -328,31 +324,16 @@ public:
}
private:
int firstLine, lastNumLines;
int firstLine = 0, lastNumLines = 0;
};
//==============================================================================
CodeEditorComponent::CodeEditorComponent (CodeDocument& doc, CodeTokeniser* const tokeniser)
: document (doc),
firstLineOnScreen (0),
spacesPerTab (4),
lineHeight (0),
linesOnScreen (0),
columnsOnScreen (0),
scrollbarThickness (16),
columnToTryToMaintain (-1),
readOnly (false),
useSpacesForTabs (false),
showLineNumbers (false),
shouldFollowDocumentChanges (false),
xOffset (0),
caretPos (doc, 0, 0),
selectionStart (doc, 0, 0),
selectionEnd (doc, 0, 0),
verticalScrollBar (true),
horizontalScrollBar (false),
appCommandManager (nullptr),
codeTokeniser (tokeniser)
{
pimpl = new Pimpl (*this);
@ -474,20 +455,18 @@ void CodeEditorComponent::resized()
void CodeEditorComponent::paint (Graphics& g)
{
pimpl->handleUpdateNowIfNeeded();
g.fillAll (findColour (CodeEditorComponent::backgroundColourId));
const int gutterSize = getGutterSize();
auto gutterSize = getGutterSize();
g.reduceClipRegion (gutterSize, 0, verticalScrollBar.getX() - gutterSize, horizontalScrollBar.getY());
g.setFont (font);
const Rectangle<int> clip (g.getClipBounds());
const int firstLineToDraw = jmax (0, clip.getY() / lineHeight);
const int lastLineToDraw = jmin (lines.size(), clip.getBottom() / lineHeight + 1);
const float x = (float) (gutterSize - xOffset * charWidth);
const float rightClip = (float) clip.getRight();
auto clip = g.getClipBounds();
auto firstLineToDraw = jmax (0, clip.getY() / lineHeight);
auto lastLineToDraw = jmin (lines.size(), clip.getBottom() / lineHeight + 1);
auto x = (float) (gutterSize - xOffset * charWidth);
auto rightClip = (float) clip.getRight();
{
RectangleList<float> highlightArea;
@ -727,10 +706,11 @@ void CodeEditorComponent::scrollToKeepCaretOnScreen()
{
if (getWidth() > 0 && getHeight() > 0)
{
const int caretLine = caretPos.getLineNumber();
scrollToKeepLinesOnScreen (Range<int> (caretLine, caretLine));
auto caretLine = caretPos.getLineNumber();
scrollToKeepLinesOnScreen ({ caretLine, caretLine });
auto column = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine());
const int column = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine());
if (column >= xOffset + columnsOnScreen - 1)
scrollToColumn (column + 1 - columnsOnScreen);
else if (column < xOffset)
@ -740,10 +720,10 @@ void CodeEditorComponent::scrollToKeepCaretOnScreen()
Rectangle<int> CodeEditorComponent::getCharacterBounds (const CodeDocument::Position& pos) const
{
return Rectangle<int> (roundToInt ((getGutterSize() - xOffset * charWidth) + indexToColumn (pos.getLineNumber(), pos.getIndexInLine()) * charWidth),
(pos.getLineNumber() - firstLineOnScreen) * lineHeight,
roundToInt (charWidth),
lineHeight);
return { roundToInt ((getGutterSize() - xOffset * charWidth) + indexToColumn (pos.getLineNumber(), pos.getIndexInLine()) * charWidth),
(pos.getLineNumber() - firstLineOnScreen) * lineHeight,
roundToInt (charWidth),
lineHeight };
}
CodeDocument::Position CodeEditorComponent::getPositionAt (int x, int y)
@ -786,8 +766,8 @@ void CodeEditorComponent::insertTabAtCaret()
if (useSpacesForTabs)
{
const int caretCol = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine());
const int spacesNeeded = spacesPerTab - (caretCol % spacesPerTab);
auto caretCol = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine());
auto spacesNeeded = spacesPerTab - (caretCol % spacesPerTab);
insertTextAtCaret (String::repeatedString (" ", spacesNeeded));
}
else
@ -803,7 +783,7 @@ bool CodeEditorComponent::deleteWhitespaceBackwardsToTabStop()
{
for (;;)
{
const int currentColumn = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine());
auto currentColumn = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine());
if (currentColumn <= 0 || (currentColumn % spacesPerTab) == 0)
break;
@ -811,7 +791,7 @@ bool CodeEditorComponent::deleteWhitespaceBackwardsToTabStop()
moveCaretLeft (false, true);
}
const String selected (getTextInRange (getHighlightedRegion()));
auto selected = getTextInRange (getHighlightedRegion());
if (selected.isNotEmpty() && selected.trim().isEmpty())
{
@ -845,8 +825,8 @@ void CodeEditorComponent::indentSelectedLines (const int spacesToAdd)
for (int line = lineStart; line <= lineEnd; ++line)
{
const String lineText (document.getLine (line));
const int nonWhitespaceStart = CodeEditorHelpers::findFirstNonWhitespaceChar (lineText);
auto lineText = document.getLine (line);
auto nonWhitespaceStart = CodeEditorHelpers::findFirstNonWhitespaceChar (lineText);
if (nonWhitespaceStart > 0 || lineText.trimStart().isNotEmpty())
{
@ -872,13 +852,13 @@ void CodeEditorComponent::indentSelectedLines (const int spacesToAdd)
void CodeEditorComponent::cut()
{
insertText (String());
insertText ({});
}
bool CodeEditorComponent::copyToClipboard()
{
newTransaction();
const String selection (document.getTextBetween (selectionStart, selectionEnd));
auto selection = document.getTextBetween (selectionStart, selectionEnd);
if (selection.isNotEmpty())
SystemClipboard::copyTextToClipboard (selection);
@ -897,7 +877,7 @@ bool CodeEditorComponent::cutToClipboard()
bool CodeEditorComponent::pasteFromClipboard()
{
newTransaction();
const String clip (SystemClipboard::getTextFromClipboard());
auto clip = SystemClipboard::getTextFromClipboard();
if (clip.isNotEmpty())
insertText (clip);
@ -957,14 +937,14 @@ bool CodeEditorComponent::moveCaretRight (const bool moveInWholeWordSteps, const
void CodeEditorComponent::moveLineDelta (const int delta, const bool selecting)
{
CodeDocument::Position pos (caretPos);
const int newLineNum = pos.getLineNumber() + delta;
auto newLineNum = pos.getLineNumber() + delta;
if (columnToTryToMaintain < 0)
columnToTryToMaintain = indexToColumn (pos.getLineNumber(), pos.getIndexInLine());
pos.setLineAndIndex (newLineNum, columnToIndex (newLineNum, columnToTryToMaintain));
const int colToMaintain = columnToTryToMaintain;
auto colToMaintain = columnToTryToMaintain;
moveCaretTo (pos, selecting);
columnToTryToMaintain = colToMaintain;
}
@ -1085,8 +1065,8 @@ bool CodeEditorComponent::deleteBackwards (const bool moveInWholeWordSteps)
bool CodeEditorComponent::skipBackwardsToPreviousTab()
{
const String currentLineText (caretPos.getLineText().removeCharacters ("\r\n"));
const int currentIndex = caretPos.getIndexInLine();
auto currentLineText = caretPos.getLineText().removeCharacters ("\r\n");
auto currentIndex = caretPos.getIndexInLine();
if (currentLineText.isNotEmpty() && currentLineText.length() == currentIndex)
{
@ -1177,7 +1157,8 @@ void CodeEditorComponent::setCommandManager (ApplicationCommandManager* newManag
//==============================================================================
Range<int> CodeEditorComponent::getHighlightedRegion() const
{
return Range<int> (selectionStart.getPosition(), selectionEnd.getPosition());
return { selectionStart.getPosition(),
selectionEnd.getPosition() };
}
bool CodeEditorComponent::isHighlightActive() const noexcept
@ -1463,10 +1444,10 @@ String CodeEditorComponent::getTabString (const int numSpaces) const
int CodeEditorComponent::indexToColumn (int lineNum, int index) const noexcept
{
const String line (document.getLine (lineNum));
String::CharPointerType t (line.getCharPointer());
auto line = document.getLine (lineNum);
auto t = line.getCharPointer();
int col = 0;
for (int i = 0; i < index; ++i)
{
if (t.isEmpty())
@ -1486,9 +1467,8 @@ int CodeEditorComponent::indexToColumn (int lineNum, int index) const noexcept
int CodeEditorComponent::columnToIndex (int lineNum, int column) const noexcept
{
const String line (document.getLine (lineNum));
String::CharPointerType t (line.getCharPointer());
auto line = document.getLine (lineNum);
auto t = line.getCharPointer();
int i = 0, col = 0;
while (! t.isEmpty())
@ -1516,12 +1496,10 @@ void CodeEditorComponent::setFont (const Font& newFont)
resized();
}
void CodeEditorComponent::ColourScheme::set (const String& name, const Colour colour)
void CodeEditorComponent::ColourScheme::set (const String& name, Colour colour)
{
for (int i = 0; i < types.size(); ++i)
for (auto& tt : types)
{
TokenType& tt = types.getReference(i);
if (tt.name == name)
{
tt.colour = colour;
@ -1570,12 +1548,12 @@ void CodeEditorComponent::updateCachedIterators (int maxLineNum)
{
for (;;)
{
CodeDocument::Iterator& last = *cachedIterators.getLast();
auto& last = *cachedIterators.getLast();
if (last.getLine() >= maxLineNum)
break;
CodeDocument::Iterator* t = new CodeDocument::Iterator (last);
auto* t = new CodeDocument::Iterator (last);
cachedIterators.add (t);
const int targetLine = jmin (maxLineNum, last.getLine() + linesBetweenCachedSources);
@ -1599,7 +1577,8 @@ void CodeEditorComponent::getIteratorForPosition (int position, CodeDocument::It
{
for (int i = cachedIterators.size(); --i >= 0;)
{
const CodeDocument::Iterator& t = *cachedIterators.getUnchecked (i);
auto& t = *cachedIterators.getUnchecked (i);
if (t.getPosition() <= position)
{
source = t;
@ -1626,7 +1605,7 @@ CodeEditorComponent::State::State (const CodeEditorComponent& editor)
lastCaretPos (editor.getCaretPos().getPosition()),
lastSelectionEnd (lastCaretPos)
{
const Range<int> selection (editor.getHighlightedRegion());
auto selection = editor.getHighlightedRegion();
if (lastCaretPos == selection.getStart())
lastSelectionEnd = selection.getEnd();
@ -1652,8 +1631,7 @@ void CodeEditorComponent::State::restoreState (CodeEditorComponent& editor) cons
CodeEditorComponent::State::State (const String& s)
{
StringArray tokens;
tokens.addTokens (s, ":", StringRef());
auto tokens = StringArray::fromTokens (s, ":", {});
lastTopLine = tokens[0].getIntValue();
lastCaretPos = tokens[1].getIntValue();

View file

@ -228,7 +228,7 @@ public:
Array<TokenType> types;
void set (const String& name, const Colour colour);
void set (const String& name, Colour colour);
};
/** Changes the syntax highlighting scheme.
@ -364,18 +364,17 @@ private:
CodeDocument& document;
Font font;
int firstLineOnScreen, spacesPerTab;
float charWidth;
int lineHeight, linesOnScreen, columnsOnScreen;
int scrollbarThickness, columnToTryToMaintain;
bool readOnly, useSpacesForTabs, showLineNumbers, shouldFollowDocumentChanges;
double xOffset;
int firstLineOnScreen = 0, spacesPerTab = 4;
float charWidth = 0;
int lineHeight = 0, linesOnScreen = 0, columnsOnScreen = 0;
int scrollbarThickness = 16, columnToTryToMaintain = -1;
bool readOnly = false, useSpacesForTabs = true, showLineNumbers = false, shouldFollowDocumentChanges = false;
double xOffset = 0;
CodeDocument::Position caretPos, selectionStart, selectionEnd;
ScopedPointer<CaretComponent> caret;
ScrollBar verticalScrollBar, horizontalScrollBar;
ApplicationCommandManager* appCommandManager;
ScrollBar verticalScrollBar { true }, horizontalScrollBar { false };
ApplicationCommandManager* appCommandManager = nullptr;
class Pimpl;
friend class Pimpl;
@ -394,7 +393,7 @@ private:
draggingSelectionEnd
};
DragType dragType;
DragType dragType = notDragging;
//==============================================================================
CodeTokeniser* codeTokeniser;