Browse Source

bug-fix: vim mode cursor width

Le Tan 8 years ago
parent
commit
0d6ed84228
4 changed files with 57 additions and 43 deletions
  1. 1 19
      src/utils/vvim.cpp
  2. 28 13
      src/vtextdocumentlayout.cpp
  3. 16 0
      src/vtextdocumentlayout.h
  4. 12 11
      src/vtextedit.cpp

+ 1 - 19
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);

+ 28 - 13
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 QVector<VPreviewInf
 
     return maxHeight;
 }
+
+int VTextDocumentLayout::getTextWidthWithinTextLine(const QTextLayout *p_layout,
+                                                    int p_pos,
+                                                    int p_length)
+{
+    QTextLine line = p_layout->lineForTextPosition(p_pos);
+    Q_ASSERT(p_pos + p_length <= line.textStart() + line.textLength());
+    return line.cursorToX(p_pos + p_length) - line.cursorToX(p_pos);
+}

+ 16 - 0
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

+ 12 - 11
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);
     }
 }