void CodeEditorComponent::resized()
{
    linesOnScreen = (getHeight() - scrollbarThickness) / lineHeight;
    columnsOnScreen = (int) ((getWidth() - scrollbarThickness) / charWidth);
    lines.clear();
    rebuildLineTokens();
    updateCaretPosition();

    verticalScrollBar.setBounds (getWidth() - scrollbarThickness, 0, scrollbarThickness, getHeight() - scrollbarThickness);
    horizontalScrollBar.setBounds (gutter, getHeight() - scrollbarThickness, getWidth() - scrollbarThickness - gutter, scrollbarThickness);
    updateScrollBars();
}
void CodeEditorComponent::scrollToLineInternal (int newFirstLineOnScreen)
{
    newFirstLineOnScreen = jlimit (0, jmax (0, document.getNumLines() - 1),
                                   newFirstLineOnScreen);

    if (newFirstLineOnScreen != firstLineOnScreen)
    {
        firstLineOnScreen = newFirstLineOnScreen;
        updateCaretPosition();

        updateCachedIterators (firstLineOnScreen);
        triggerAsyncUpdate();
    }
}
void CodeEditorComponent::scrollToLineInternal (int newFirstLineOnScreen)
{
    newFirstLineOnScreen = jlimit (0, jmax (0, document.getNumLines() - 1),
                                   newFirstLineOnScreen);

    if (newFirstLineOnScreen != firstLineOnScreen)
    {
        firstLineOnScreen = newFirstLineOnScreen;
        updateCaretPosition();

        updateCachedIterators (firstLineOnScreen);
        rebuildLineTokensAsync();
        pimpl->handleUpdateNowIfNeeded();
    }
}
//==============================================================================
void CodeEditorComponent::resized()
{
    const int visibleWidth = getWidth() - scrollbarThickness - getGutterSize();
    linesOnScreen   = jmax (1, (getHeight() - scrollbarThickness) / lineHeight);
    columnsOnScreen = jmax (1, (int) (visibleWidth / charWidth));
    lines.clear();
    rebuildLineTokens();
    updateCaretPosition();

    if (gutter != nullptr)
        gutter->setBounds (0, 0, getGutterSize() - 2, getHeight());

    verticalScrollBar.setBounds (getWidth() - scrollbarThickness, 0,
                                 scrollbarThickness, getHeight() - scrollbarThickness);

    horizontalScrollBar.setBounds (getGutterSize(), getHeight() - scrollbarThickness,
                                   visibleWidth, scrollbarThickness);
    updateScrollBars();
}
//==============================================================================
void CodeEditorComponent::codeDocumentChanged (const CodeDocument::Position& affectedTextStart,
                                               const CodeDocument::Position& affectedTextEnd)
{
    clearCachedIterators (affectedTextStart.getLineNumber());

    triggerAsyncUpdate();

    updateCaretPosition();
    columnToTryToMaintain = -1;

    if (affectedTextEnd.getPosition() >= selectionStart.getPosition()
         && affectedTextStart.getPosition() <= selectionEnd.getPosition())
        deselectAll();

    if (caretPos.getPosition() > affectedTextEnd.getPosition()
         || caretPos.getPosition() < affectedTextStart.getPosition())
        moveCaretTo (affectedTextStart, false);

    updateScrollBars();
}
void CodeEditorComponent::codeDocumentChanged (const int startIndex, const int endIndex)
{
    const CodeDocument::Position affectedTextStart (document, startIndex);
    const CodeDocument::Position affectedTextEnd (document, endIndex);

    clearCachedIterators (affectedTextStart.getLineNumber());

    rebuildLineTokensAsync();

    updateCaretPosition();
    columnToTryToMaintain = -1;

    if (affectedTextEnd.getPosition() >= selectionStart.getPosition()
         && affectedTextStart.getPosition() <= selectionEnd.getPosition())
        deselectAll();

    if (caretPos.getPosition() > affectedTextEnd.getPosition()
         || caretPos.getPosition() < affectedTextStart.getPosition())
        moveCaretTo (affectedTextStart, false);

    updateScrollBars();
}
void CodeEditorComponent::focusLost (FocusChangeType)
{
    updateCaretPosition();
}