From 0d6ed84228a82e8035e04683545d24212131b301 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Fri, 1 Dec 2017 23:24:21 +0800 Subject: [PATCH] bug-fix: vim mode cursor width --- src/utils/vvim.cpp | 20 +----------------- src/vtextdocumentlayout.cpp | 41 +++++++++++++++++++++++++------------ src/vtextdocumentlayout.h | 16 +++++++++++++++ src/vtextedit.cpp | 23 +++++++++++---------- 4 files changed, 57 insertions(+), 43 deletions(-) diff --git a/src/utils/vvim.cpp b/src/utils/vvim.cpp index e0c1e195..03c10d9a 100644 --- a/src/utils/vvim.cpp +++ b/src/utils/vvim.cpp @@ -2240,25 +2240,7 @@ void VVim::setMode(VimMode p_mode, bool p_clearSelection) m_mode = p_mode; resetState(); - bool cursorBlock = false; - switch (m_mode) { - case VimMode::Insert: - cursorBlock = true; - m_editor->setCursorBlockColor(g_config->getEditorVimInsertCursorBg(), - g_config->getEditorVimInsertCursorFg()); - break; - - case VimMode::Normal: - cursorBlock = true; - m_editor->setCursorBlockColor(g_config->getEditorVimNormalCursorBg(), - g_config->getEditorVimNormalCursorFg()); - break; - - default: - break; - } - - m_editor->setCursorBlockEnabled(cursorBlock); + m_editor->setCursorBlockEnabled(checkMode(VimMode::Normal)); emit modeChanged(m_mode); emit vimStatusUpdated(this); diff --git a/src/vtextdocumentlayout.cpp b/src/vtextdocumentlayout.cpp index 55fd3806..47dd8e3c 100644 --- a/src/vtextdocumentlayout.cpp +++ b/src/vtextdocumentlayout.cpp @@ -35,7 +35,8 @@ VTextDocumentLayout::VTextDocumentLayout(QTextDocument *p_doc, m_cursorBlockMode(false), m_virtualCursorBlockWidth(8), m_cursorBlockFg("#EEEEEE"), - m_cursorBlockBg("#222222") + m_cursorBlockBg("#222222"), + m_lastCursorBlockWidth(-1) { } @@ -230,17 +231,23 @@ void VTextDocumentLayout::draw(QPainter *p_painter, const PaintContext &p_contex int bllen = block.length(); bool drawCursor = p_context.cursorPosition >= blpos && p_context.cursorPosition < blpos + bllen; - bool drawCursorAsBlock = drawCursor && m_cursorBlockMode; - if (drawCursorAsBlock) { + int cursorWidth = m_cursorWidth; + if (drawCursor && m_cursorBlockMode) { if (p_context.cursorPosition == blpos + bllen - 1) { - drawCursorAsBlock = false; + cursorWidth = m_virtualCursorBlockWidth; } else { - QTextLayout::FormatRange o; - o.start = p_context.cursorPosition - blpos; - o.length = 1; - o.format.setForeground(m_cursorBlockFg); - o.format.setBackground(m_cursorBlockBg); - selections.append(o); + // Get the width of the selection to update cursor width. + cursorWidth = getTextWidthWithinTextLine(layout, + p_context.cursorPosition - blpos, + 1); + if (cursorWidth < m_cursorWidth) { + cursorWidth = m_cursorWidth; + } + } + + if (cursorWidth != m_lastCursorBlockWidth) { + m_lastCursorBlockWidth = cursorWidth; + emit cursorBlockWidthUpdated(m_lastCursorBlockWidth); } } @@ -253,7 +260,7 @@ void VTextDocumentLayout::draw(QPainter *p_painter, const PaintContext &p_contex drawMarkers(p_painter, block, offset); - if ((drawCursor && !drawCursorAsBlock) + if (drawCursor || (p_context.cursorPosition < -1 && !layout->preeditAreaText().isEmpty())) { int cpos = p_context.cursorPosition; @@ -266,8 +273,7 @@ void VTextDocumentLayout::draw(QPainter *p_painter, const PaintContext &p_contex layout->drawCursor(p_painter, offset, cpos, - m_cursorBlockMode ? m_virtualCursorBlockWidth - : m_cursorWidth); + cursorWidth); } offset.ry() += rect.height(); @@ -1074,3 +1080,12 @@ qreal VTextDocumentLayout::fetchInlineImagesForOneLine(const QVectorlineForTextPosition(p_pos); + Q_ASSERT(p_pos + p_length <= line.textStart() + line.textLength()); + return line.cursorToX(p_pos + p_length) - line.cursorToX(p_pos); +} diff --git a/src/vtextdocumentlayout.h b/src/vtextdocumentlayout.h index 66e2e591..785a64eb 100644 --- a/src/vtextdocumentlayout.h +++ b/src/vtextdocumentlayout.h @@ -60,6 +60,12 @@ public: void setCursorBlockBg(const QColor &p_color); + void setVirtualCursorBlockWidth(int p_width); + +signals: + // Emit to update current cursor block width if m_cursorBlockMode is enabled. + void cursorBlockWidthUpdated(int p_width); + protected: void documentChanged(int p_from, int p_charsRemoved, int p_charsAdded) Q_DECL_OVERRIDE; @@ -235,6 +241,10 @@ private: void scaleSize(QSize &p_size, int p_width, int p_height); + // Get text length in pixel. + // @p_pos: position within the layout. + int getTextWidthWithinTextLine(const QTextLayout *p_layout, int p_pos, int p_length); + // Document margin on left/right/bottom. qreal m_margin; @@ -282,6 +292,8 @@ private: // Background of cursor block. QColor m_cursorBlockBg; + + int m_lastCursorBlockWidth; }; inline qreal VTextDocumentLayout::getLineLeading() const @@ -316,4 +328,8 @@ inline void VTextDocumentLayout::setCursorBlockBg(const QColor &p_color) m_cursorBlockBg = p_color; } +inline void VTextDocumentLayout::setVirtualCursorBlockWidth(int p_width) +{ + m_virtualCursorBlockWidth = p_width; +} #endif // VTEXTDOCUMENTLAYOUT_H diff --git a/src/vtextedit.cpp b/src/vtextedit.cpp index 0c8b66c9..e18684ea 100644 --- a/src/vtextedit.cpp +++ b/src/vtextedit.cpp @@ -8,6 +8,7 @@ #include "vtextdocumentlayout.h" #include "vimageresourcemanager2.h" +#define VIRTUAL_CURSOR_BLOCK_WIDTH 8 enum class BlockState { @@ -57,6 +58,16 @@ void VTextEdit::init() docLayout->setBlockImageEnabled(m_blockImageEnabled); doc->setDocumentLayout(docLayout); + docLayout->setVirtualCursorBlockWidth(VIRTUAL_CURSOR_BLOCK_WIDTH); + + connect(docLayout, &VTextDocumentLayout::cursorBlockWidthUpdated, + this, [this](int p_width) { + if (p_width != cursorWidth() + && p_width > VIRTUAL_CURSOR_BLOCK_WIDTH) { + setCursorWidth(p_width); + } + }); + m_lineNumberArea = new VLineNumberArea(this, document(), fontMetrics().width(QLatin1Char('8')), @@ -86,10 +97,6 @@ void VTextEdit::resizeEvent(QResizeEvent *p_event) { QTextEdit::resizeEvent(p_event); - if (m_cursorBlockMode) { - setCursorWidth(p_event->size().width()); - } - if (m_lineNumberType != LineNumberType::None) { QRect rect = contentsRect(); m_lineNumberArea->setGeometry(QRect(rect.left(), @@ -345,13 +352,7 @@ void VTextEdit::setCursorBlockMode(bool p_enabled) m_cursorBlockMode = p_enabled; getLayout()->setCursorBlockMode(m_cursorBlockMode); - if (p_enabled) { - // Will set cursor width according to the viewport. - setCursorWidth(viewport()->width()); - } else { - // Restore cursor width. - setCursorWidth(1); - } + setCursorWidth(m_cursorBlockMode ? VIRTUAL_CURSOR_BLOCK_WIDTH : 1); } }