forked from qt-creator/qt-creator
Editor: improve visual indent depth for empty blocks
Use the indenter based visual indent only for the cpp qt style indenter since it gives accurate results. In all other casess Look for the next and previous not empty lines and use the minimum indent depth of those lines as the visual indent depth for empty lines. Task-number: QTCREATORBUG-28179 Change-Id: Ic456fba5adfb2a12f20e2bd4fc663010c752b65c Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -157,6 +157,12 @@ int CppQtStyleIndenter::indentFor(const QTextBlock &block,
|
|||||||
return indent;
|
return indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CppQtStyleIndenter::visualIndentFor(const QTextBlock &block,
|
||||||
|
const TextEditor::TabSettings &tabSettings)
|
||||||
|
{
|
||||||
|
return indentFor(block, tabSettings);
|
||||||
|
}
|
||||||
|
|
||||||
CppCodeStyleSettings CppQtStyleIndenter::codeStyleSettings() const
|
CppCodeStyleSettings CppQtStyleIndenter::codeStyleSettings() const
|
||||||
{
|
{
|
||||||
if (m_cppCodeStylePreferences)
|
if (m_cppCodeStylePreferences)
|
||||||
|
@@ -34,6 +34,8 @@ public:
|
|||||||
int indentFor(const QTextBlock &block,
|
int indentFor(const QTextBlock &block,
|
||||||
const TextEditor::TabSettings &tabSettings,
|
const TextEditor::TabSettings &tabSettings,
|
||||||
int cursorPositionInEditor = -1) override;
|
int cursorPositionInEditor = -1) override;
|
||||||
|
int visualIndentFor(const QTextBlock &block,
|
||||||
|
const TextEditor::TabSettings &tabSettings) override;
|
||||||
TextEditor::IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
|
TextEditor::IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
|
||||||
const TextEditor::TabSettings &tabSettings,
|
const TextEditor::TabSettings &tabSettings,
|
||||||
int cursorPositionInEditor = -1) override;
|
int cursorPositionInEditor = -1) override;
|
||||||
|
@@ -67,6 +67,11 @@ int Indenter::indentFor(const QTextBlock &block,
|
|||||||
return codeFormatter.indentFor(block);
|
return codeFormatter.indentFor(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Indenter::visualIndentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings)
|
||||||
|
{
|
||||||
|
return indentFor(block, tabSettings);
|
||||||
|
}
|
||||||
|
|
||||||
TextEditor::IndentationForBlock Indenter::indentationForBlocks(
|
TextEditor::IndentationForBlock Indenter::indentationForBlocks(
|
||||||
const QVector<QTextBlock> &blocks,
|
const QVector<QTextBlock> &blocks,
|
||||||
const TextEditor::TabSettings &tabSettings,
|
const TextEditor::TabSettings &tabSettings,
|
||||||
|
@@ -26,6 +26,8 @@ public:
|
|||||||
int indentFor(const QTextBlock &block,
|
int indentFor(const QTextBlock &block,
|
||||||
const TextEditor::TabSettings &tabSettings,
|
const TextEditor::TabSettings &tabSettings,
|
||||||
int cursorPositionInEditor = -1) override;
|
int cursorPositionInEditor = -1) override;
|
||||||
|
int visualIndentFor(const QTextBlock &block,
|
||||||
|
const TextEditor::TabSettings &tabSettings) override;
|
||||||
TextEditor::IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
|
TextEditor::IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
|
||||||
const TextEditor::TabSettings &tabSettings,
|
const TextEditor::TabSettings &tabSettings,
|
||||||
int cursorPositionInEditor = -1) override;
|
int cursorPositionInEditor = -1) override;
|
||||||
|
@@ -57,6 +57,12 @@ public:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int visualIndentFor(const QTextBlock & /*block*/,
|
||||||
|
const TabSettings & /*tabSettings*/)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void autoIndent(const QTextCursor &cursor,
|
virtual void autoIndent(const QTextCursor &cursor,
|
||||||
const TabSettings &tabSettings,
|
const TabSettings &tabSettings,
|
||||||
int cursorPositionInEditor = -1)
|
int cursorPositionInEditor = -1)
|
||||||
|
@@ -513,6 +513,7 @@ public:
|
|||||||
void updateHighlights();
|
void updateHighlights();
|
||||||
void updateCurrentLineInScrollbar();
|
void updateCurrentLineInScrollbar();
|
||||||
void updateCurrentLineHighlight();
|
void updateCurrentLineHighlight();
|
||||||
|
int indentDepthForBlock(const QTextBlock &block);
|
||||||
|
|
||||||
void drawFoldingMarker(QPainter *painter, const QPalette &pal,
|
void drawFoldingMarker(QPainter *painter, const QPalette &pal,
|
||||||
const QRect &rect,
|
const QRect &rect,
|
||||||
@@ -533,7 +534,7 @@ public:
|
|||||||
void paintCursorAsBlock(const PaintEventData &data, QPainter &painter,
|
void paintCursorAsBlock(const PaintEventData &data, QPainter &painter,
|
||||||
PaintEventBlockData &blockData, int cursorPosition) const;
|
PaintEventBlockData &blockData, int cursorPosition) const;
|
||||||
void paintAdditionalVisualWhitespaces(PaintEventData &data, QPainter &painter, qreal top) const;
|
void paintAdditionalVisualWhitespaces(PaintEventData &data, QPainter &painter, qreal top) const;
|
||||||
void paintIndentDepth(PaintEventData &data, QPainter &painter, const PaintEventBlockData &blockData) const;
|
void paintIndentDepth(PaintEventData &data, QPainter &painter, const PaintEventBlockData &blockData);
|
||||||
void paintReplacement(PaintEventData &data, QPainter &painter, qreal top) const;
|
void paintReplacement(PaintEventData &data, QPainter &painter, qreal top) const;
|
||||||
void paintWidgetBackground(const PaintEventData &data, QPainter &painter) const;
|
void paintWidgetBackground(const PaintEventData &data, QPainter &painter) const;
|
||||||
void paintOverlays(const PaintEventData &data, QPainter &painter) const;
|
void paintOverlays(const PaintEventData &data, QPainter &painter) const;
|
||||||
@@ -808,6 +809,7 @@ public:
|
|||||||
};
|
};
|
||||||
using UndoMultiCursor = QList<UndoCursor>;
|
using UndoMultiCursor = QList<UndoCursor>;
|
||||||
QStack<UndoMultiCursor> m_undoCursorStack;
|
QStack<UndoMultiCursor> m_undoCursorStack;
|
||||||
|
QList<int> m_visualIndentCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextEditorWidgetFind : public BaseTextFind
|
class TextEditorWidgetFind : public BaseTextFind
|
||||||
@@ -1852,6 +1854,7 @@ void TextEditorWidgetPrivate::editorContentsChange(int position, int charsRemove
|
|||||||
}
|
}
|
||||||
m_blockCount = newBlockCount;
|
m_blockCount = newBlockCount;
|
||||||
m_scrollBarUpdateTimer.start(500);
|
m_scrollBarUpdateTimer.start(500);
|
||||||
|
m_visualIndentCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditorWidgetPrivate::slotSelectionChanged()
|
void TextEditorWidgetPrivate::slotSelectionChanged()
|
||||||
@@ -4379,24 +4382,72 @@ void TextEditorWidgetPrivate::paintAdditionalVisualWhitespaces(PaintEventData &d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TextEditorWidgetPrivate::indentDepthForBlock(const QTextBlock &block)
|
||||||
|
{
|
||||||
|
const TabSettings &tabSettings = m_document->tabSettings();
|
||||||
|
const auto blockDepth = [&](const QTextBlock &block) {
|
||||||
|
int depth = m_visualIndentCache.value(block.blockNumber(), -1);
|
||||||
|
if (depth < 0) {
|
||||||
|
const QString text = block.text();
|
||||||
|
depth = text.simplified().isEmpty() ? -1 : tabSettings.indentationColumn(text);
|
||||||
|
}
|
||||||
|
return depth;
|
||||||
|
};
|
||||||
|
const auto ensureCacheSize = [&](const int size) {
|
||||||
|
if (m_visualIndentCache.size() < size)
|
||||||
|
m_visualIndentCache.resize(size, -1);
|
||||||
|
};
|
||||||
|
int depth = blockDepth(block);
|
||||||
|
if (depth < 0) // the block was empty and uncached ask the indenter for a visual indentation
|
||||||
|
depth = m_document->indenter()->visualIndentFor(block, tabSettings);
|
||||||
|
if (depth >= 0) {
|
||||||
|
ensureCacheSize(block.blockNumber() + 1);
|
||||||
|
m_visualIndentCache[block.blockNumber()] = depth;
|
||||||
|
} else {
|
||||||
|
// find previous non empty block and get the indent depth of this block
|
||||||
|
QTextBlock it = block.previous();
|
||||||
|
int prevDepth = -1;
|
||||||
|
while (it.isValid()) {
|
||||||
|
prevDepth = blockDepth(it);
|
||||||
|
if (prevDepth >= 0)
|
||||||
|
break;
|
||||||
|
it = it.previous();
|
||||||
|
}
|
||||||
|
const int startBlockNumber = it.isValid() ? it.blockNumber() + 1 : 0;
|
||||||
|
|
||||||
|
// find next non empty block and get the indent depth of this block
|
||||||
|
it = block.next();
|
||||||
|
int nextDepth = -1;
|
||||||
|
while (it.isValid()) {
|
||||||
|
nextDepth = blockDepth(it);
|
||||||
|
if (nextDepth >= 0)
|
||||||
|
break;
|
||||||
|
it = it.next();
|
||||||
|
}
|
||||||
|
const int endBlockNumber = it.isValid() ? it.blockNumber() : m_blockCount;
|
||||||
|
|
||||||
|
// get the depth for the whole range of empty blocks and fill the cache so we do not need to
|
||||||
|
// redo this for every paint event
|
||||||
|
depth = prevDepth > 0 && nextDepth > 0 ? qMin(prevDepth, nextDepth) : 0;
|
||||||
|
ensureCacheSize(endBlockNumber);
|
||||||
|
for (int i = startBlockNumber; i < endBlockNumber; ++i)
|
||||||
|
m_visualIndentCache[i] = depth;
|
||||||
|
}
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
void TextEditorWidgetPrivate::paintIndentDepth(PaintEventData &data,
|
void TextEditorWidgetPrivate::paintIndentDepth(PaintEventData &data,
|
||||||
QPainter &painter,
|
QPainter &painter,
|
||||||
const PaintEventBlockData &blockData) const
|
const PaintEventBlockData &blockData)
|
||||||
{
|
{
|
||||||
if (!m_displaySettings.m_visualizeIndent)
|
if (!m_displaySettings.m_visualizeIndent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QString text = data.block.text();
|
const int depth = indentDepthForBlock(data.block);
|
||||||
const TabSettings &tabSettings = m_document->tabSettings();
|
if (depth <= 0 || blockData.layout->lineCount() < 1)
|
||||||
int currentDepth = -1;
|
|
||||||
if (text.simplified().isEmpty())
|
|
||||||
currentDepth = m_document->indenter()->indentFor(data.block, tabSettings);
|
|
||||||
if (currentDepth < 0)
|
|
||||||
currentDepth = tabSettings.indentationColumn(text);
|
|
||||||
|
|
||||||
if (currentDepth == 0 || blockData.layout->lineCount() < 1)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const TabSettings &tabSettings = m_document->tabSettings();
|
||||||
const qreal horizontalAdvance = QFontMetricsF(q->font()).horizontalAdvance(
|
const qreal horizontalAdvance = QFontMetricsF(q->font()).horizontalAdvance(
|
||||||
QString(tabSettings.m_indentSize, QChar(' ')));
|
QString(tabSettings.m_indentSize, QChar(' ')));
|
||||||
|
|
||||||
@@ -4408,7 +4459,8 @@ void TextEditorWidgetPrivate::paintIndentDepth(PaintEventData &data,
|
|||||||
qreal x = textLine.cursorToX(0) + data.offset.x() + qMax(0, q->cursorWidth() - 1);
|
qreal x = textLine.cursorToX(0) + data.offset.x() + qMax(0, q->cursorWidth() - 1);
|
||||||
int paintColumn = 0;
|
int paintColumn = 0;
|
||||||
|
|
||||||
while (paintColumn < currentDepth) {
|
const QString text = data.block.text();
|
||||||
|
while (paintColumn < depth) {
|
||||||
if (x >= 0) {
|
if (x >= 0) {
|
||||||
int paintPosition = tabSettings.positionAtColumn(text, paintColumn);
|
int paintPosition = tabSettings.positionAtColumn(text, paintColumn);
|
||||||
if (blockData.layout->lineForTextPosition(paintPosition).lineNumber() != 0)
|
if (blockData.layout->lineForTextPosition(paintPosition).lineNumber() != 0)
|
||||||
|
Reference in New Issue
Block a user