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;
|
||||
}
|
||||
|
||||
int CppQtStyleIndenter::visualIndentFor(const QTextBlock &block,
|
||||
const TextEditor::TabSettings &tabSettings)
|
||||
{
|
||||
return indentFor(block, tabSettings);
|
||||
}
|
||||
|
||||
CppCodeStyleSettings CppQtStyleIndenter::codeStyleSettings() const
|
||||
{
|
||||
if (m_cppCodeStylePreferences)
|
||||
|
@@ -34,6 +34,8 @@ public:
|
||||
int indentFor(const QTextBlock &block,
|
||||
const TextEditor::TabSettings &tabSettings,
|
||||
int cursorPositionInEditor = -1) override;
|
||||
int visualIndentFor(const QTextBlock &block,
|
||||
const TextEditor::TabSettings &tabSettings) override;
|
||||
TextEditor::IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
|
||||
const TextEditor::TabSettings &tabSettings,
|
||||
int cursorPositionInEditor = -1) override;
|
||||
|
@@ -67,6 +67,11 @@ int Indenter::indentFor(const QTextBlock &block,
|
||||
return codeFormatter.indentFor(block);
|
||||
}
|
||||
|
||||
int Indenter::visualIndentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings)
|
||||
{
|
||||
return indentFor(block, tabSettings);
|
||||
}
|
||||
|
||||
TextEditor::IndentationForBlock Indenter::indentationForBlocks(
|
||||
const QVector<QTextBlock> &blocks,
|
||||
const TextEditor::TabSettings &tabSettings,
|
||||
|
@@ -26,6 +26,8 @@ public:
|
||||
int indentFor(const QTextBlock &block,
|
||||
const TextEditor::TabSettings &tabSettings,
|
||||
int cursorPositionInEditor = -1) override;
|
||||
int visualIndentFor(const QTextBlock &block,
|
||||
const TextEditor::TabSettings &tabSettings) override;
|
||||
TextEditor::IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
|
||||
const TextEditor::TabSettings &tabSettings,
|
||||
int cursorPositionInEditor = -1) override;
|
||||
|
@@ -57,6 +57,12 @@ public:
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual int visualIndentFor(const QTextBlock & /*block*/,
|
||||
const TabSettings & /*tabSettings*/)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual void autoIndent(const QTextCursor &cursor,
|
||||
const TabSettings &tabSettings,
|
||||
int cursorPositionInEditor = -1)
|
||||
|
@@ -513,6 +513,7 @@ public:
|
||||
void updateHighlights();
|
||||
void updateCurrentLineInScrollbar();
|
||||
void updateCurrentLineHighlight();
|
||||
int indentDepthForBlock(const QTextBlock &block);
|
||||
|
||||
void drawFoldingMarker(QPainter *painter, const QPalette &pal,
|
||||
const QRect &rect,
|
||||
@@ -533,7 +534,7 @@ public:
|
||||
void paintCursorAsBlock(const PaintEventData &data, QPainter &painter,
|
||||
PaintEventBlockData &blockData, int cursorPosition) 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 paintWidgetBackground(const PaintEventData &data, QPainter &painter) const;
|
||||
void paintOverlays(const PaintEventData &data, QPainter &painter) const;
|
||||
@@ -808,6 +809,7 @@ public:
|
||||
};
|
||||
using UndoMultiCursor = QList<UndoCursor>;
|
||||
QStack<UndoMultiCursor> m_undoCursorStack;
|
||||
QList<int> m_visualIndentCache;
|
||||
};
|
||||
|
||||
class TextEditorWidgetFind : public BaseTextFind
|
||||
@@ -1852,6 +1854,7 @@ void TextEditorWidgetPrivate::editorContentsChange(int position, int charsRemove
|
||||
}
|
||||
m_blockCount = newBlockCount;
|
||||
m_scrollBarUpdateTimer.start(500);
|
||||
m_visualIndentCache.clear();
|
||||
}
|
||||
|
||||
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,
|
||||
QPainter &painter,
|
||||
const PaintEventBlockData &blockData) const
|
||||
const PaintEventBlockData &blockData)
|
||||
{
|
||||
if (!m_displaySettings.m_visualizeIndent)
|
||||
return;
|
||||
|
||||
const QString text = data.block.text();
|
||||
const TabSettings &tabSettings = m_document->tabSettings();
|
||||
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)
|
||||
const int depth = indentDepthForBlock(data.block);
|
||||
if (depth <= 0 || blockData.layout->lineCount() < 1)
|
||||
return;
|
||||
|
||||
const TabSettings &tabSettings = m_document->tabSettings();
|
||||
const qreal horizontalAdvance = QFontMetricsF(q->font()).horizontalAdvance(
|
||||
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);
|
||||
int paintColumn = 0;
|
||||
|
||||
while (paintColumn < currentDepth) {
|
||||
const QString text = data.block.text();
|
||||
while (paintColumn < depth) {
|
||||
if (x >= 0) {
|
||||
int paintPosition = tabSettings.positionAtColumn(text, paintColumn);
|
||||
if (blockData.layout->lineForTextPosition(paintPosition).lineNumber() != 0)
|
||||
|
Reference in New Issue
Block a user