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:
parent
e58bdc9c18
commit
e6590cf095
2 changed files with 64 additions and 87 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue