Browse Source

vim-mode: make cursor block visible after actions

Le Tan 8 years ago
parent
commit
d0bcd7a2c6
4 changed files with 57 additions and 17 deletions
  1. 1 0
      src/utils/vvim.cpp
  2. 49 1
      src/vedit.cpp
  3. 6 4
      src/vedit.h
  4. 1 12
      src/vmdedit.cpp

+ 1 - 0
src/utils/vvim.cpp

@@ -2111,6 +2111,7 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
 
 clear_accept:
     resetState();
+    m_editor->makeBlockVisible(m_editor->textCursor().block());
 
 accept:
     ret = true;

+ 49 - 1
src/vedit.cpp

@@ -1168,17 +1168,65 @@ void VEdit::makeBlockVisible(const QTextBlock &p_block)
         height -= hbar->height();
     }
 
+    bool moved = false;
+
     QRectF rect = layout->blockBoundingRect(p_block);
     int y = contentOffsetY() + (int)rect.y();
+    int rectHeight = (int)rect.height();
+
+    // Handle the case rectHeight >= height.
+    if (rectHeight >= height) {
+        if (y <= 0) {
+            if (y + rectHeight < height) {
+                // Need to scroll up.
+                while (y + rectHeight < height && vbar->value() > vbar->minimum()) {
+                    moved = true;
+                    vbar->setValue(vbar->value() - vbar->singleStep());
+                    rect = layout->blockBoundingRect(p_block);
+                    rectHeight = (int)rect.height();
+                    y = contentOffsetY() + (int)rect.y();
+                }
+            }
+        } else {
+            // Need to scroll down.
+            while (y > 0 && vbar->value() < vbar->maximum()) {
+                moved = true;
+                vbar->setValue(vbar->value() + vbar->singleStep());
+                rect = layout->blockBoundingRect(p_block);
+                rectHeight = (int)rect.height();
+                y = contentOffsetY() + (int)rect.y();
+            }
+        }
+
+        if (moved) {
+            qDebug() << "scroll to make huge block visible";
+        }
+
+        return;
+    }
+
     while (y < 0 && vbar->value() > vbar->minimum()) {
+        moved = true;
         vbar->setValue(vbar->value() - vbar->singleStep());
         rect = layout->blockBoundingRect(p_block);
+        rectHeight = (int)rect.height();
         y = contentOffsetY() + (int)rect.y();
     }
 
-    while (y + (int)rect.height() > height && vbar->value() < vbar->maximum()) {
+    if (moved) {
+        qDebug() << "scroll page down to make block visible";
+        return;
+    }
+
+    while (y + rectHeight > height && vbar->value() < vbar->maximum()) {
+        moved = true;
         vbar->setValue(vbar->value() + vbar->singleStep());
         rect = layout->blockBoundingRect(p_block);
+        rectHeight = (int)rect.height();
         y = contentOffsetY() + (int)rect.y();
     }
+
+    if (moved) {
+        qDebug() << "scroll page up to make block visible";
+    }
 }

+ 6 - 4
src/vedit.h

@@ -123,6 +123,12 @@ public:
     // LineNumberArea will call this to request paint itself.
     void lineNumberAreaPaintEvent(QPaintEvent *p_event);
 
+    // Scroll the content to make @p_block visible.
+    // If the @p_block is too long to hold in one page, just let it occupy the
+    // whole page.
+    // Will not change current cursor.
+    void makeBlockVisible(const QTextBlock &p_block);
+
 signals:
     // Request VEditTab to save and exit edit mode.
     void saveAndRead();
@@ -259,10 +265,6 @@ private:
     bool findTextHelper(const QString &p_text, uint p_options,
                         bool p_forward, int p_start,
                         bool &p_wrapped, QTextCursor &p_cursor);
-
-    // Scroll the content to make @p_block visible.
-    // Will not change current cursor.
-    void makeBlockVisible(const QTextBlock &p_block);
 };
 
 class LineNumberArea : public QWidget

+ 1 - 12
src/vmdedit.cpp

@@ -30,18 +30,7 @@ VMdEdit::VMdEdit(VFile *p_file, VDocument *p_vdoc, MarkdownConverterType p_type,
     // in this case.
     connect(m_mdHighlighter, &HGMarkdownHighlighter::highlightCompleted,
             this, [this]() {
-        QRect rect = this->cursorRect();
-        int height = this->rect().height();
-        QScrollBar *sbar = this->horizontalScrollBar();
-        if (sbar && sbar->isVisible()) {
-            height -= sbar->height();
-        }
-
-        if ((rect.y() < height
-             && rect.y() + rect.height() > height)
-            || (rect.y() < 0 && rect.y() + rect.height() > 0)) {
-            this->ensureCursorVisible();
-        }
+            makeBlockVisible(textCursor().block());
     });
 
     m_cbHighlighter = new VCodeBlockHighlightHelper(m_mdHighlighter, p_vdoc,