Browse Source

VTextEdit: support block cursor

Le Tan 8 years ago
parent
commit
b2a435297d
4 changed files with 104 additions and 8 deletions
  1. 30 8
      src/vtextdocumentlayout.cpp
  2. 34 0
      src/vtextdocumentlayout.h
  3. 32 0
      src/vtextedit.cpp
  4. 8 0
      src/vtextedit.h

+ 30 - 8
src/vtextdocumentlayout.cpp

@@ -31,7 +31,11 @@ VTextDocumentLayout::VTextDocumentLayout(QTextDocument *p_doc,
       m_imageMgr(p_imageMgr),
       m_blockImageEnabled(false),
       m_imageWidthConstrainted(false),
-      m_imageLineColor("#9575CD")
+      m_imageLineColor("#9575CD"),
+      m_cursorBlockMode(false),
+      m_virtualCursorBlockWidth(8),
+      m_cursorBlockFg("#EEEEEE"),
+      m_cursorBlockBg("#222222")
 {
 }
 
@@ -221,6 +225,25 @@ void VTextDocumentLayout::draw(QPainter *p_painter, const PaintContext &p_contex
 
         auto selections = formatRangeFromSelection(block, p_context.selections);
 
+        // Draw the cursor.
+        int blpos = block.position();
+        int bllen = block.length();
+        bool drawCursor = p_context.cursorPosition >= blpos
+                          && p_context.cursorPosition < blpos + bllen;
+        bool drawCursorAsBlock = drawCursor && m_cursorBlockMode;
+        if (drawCursorAsBlock) {
+            if (p_context.cursorPosition == blpos + bllen - 1) {
+                drawCursorAsBlock = false;
+            } 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);
+            }
+        }
+
         layout->draw(p_painter,
                      offset,
                      selections,
@@ -230,12 +253,7 @@ void VTextDocumentLayout::draw(QPainter *p_painter, const PaintContext &p_contex
 
         drawMarkers(p_painter, block, offset);
 
-        // Draw the cursor.
-        int blpos = block.position();
-        int bllen = block.length();
-        bool drawCursor = p_context.cursorPosition >= blpos
-                          && p_context.cursorPosition < blpos + bllen;
-        if (drawCursor
+        if ((drawCursor && !drawCursorAsBlock)
             || (p_context.cursorPosition < -1
                 && !layout->preeditAreaText().isEmpty())) {
             int cpos = p_context.cursorPosition;
@@ -245,7 +263,11 @@ void VTextDocumentLayout::draw(QPainter *p_painter, const PaintContext &p_contex
                 cpos -= blpos;
             }
 
-            layout->drawCursor(p_painter, offset, cpos, m_cursorWidth);
+            layout->drawCursor(p_painter,
+                               offset,
+                               cpos,
+                               m_cursorBlockMode ? m_virtualCursorBlockWidth
+                                                 : m_cursorWidth);
         }
 
         offset.ry() += rect.height();

+ 34 - 0
src/vtextdocumentlayout.h

@@ -54,6 +54,12 @@ public:
 
     void setImageLineColor(const QColor &p_color);
 
+    void setCursorBlockMode(bool p_enabled);
+
+    void setCursorBlockFg(const QColor &p_color);
+
+    void setCursorBlockBg(const QColor &p_color);
+
 protected:
     void documentChanged(int p_from, int p_charsRemoved, int p_charsAdded) Q_DECL_OVERRIDE;
 
@@ -264,6 +270,18 @@ private:
 
     // Color of the image line.
     QColor m_imageLineColor;
+
+    // Draw cursor as block.
+    bool m_cursorBlockMode;
+
+    // Virtual cursor block: cursor block on no character.
+    int m_virtualCursorBlockWidth;
+
+    // Foreground of cursor block.
+    QColor m_cursorBlockFg;
+
+    // Background of cursor block.
+    QColor m_cursorBlockBg;
 };
 
 inline qreal VTextDocumentLayout::getLineLeading() const
@@ -282,4 +300,20 @@ inline void VTextDocumentLayout::scaleSize(QSize &p_size, int p_width, int p_hei
         p_size.scale(p_width, p_height, Qt::KeepAspectRatio);
     }
 }
+
+inline void VTextDocumentLayout::setCursorBlockMode(bool p_enabled)
+{
+    m_cursorBlockMode = p_enabled;
+}
+
+inline void VTextDocumentLayout::setCursorBlockFg(const QColor &p_color)
+{
+    m_cursorBlockFg = p_color;
+}
+
+inline void VTextDocumentLayout::setCursorBlockBg(const QColor &p_color)
+{
+    m_cursorBlockBg = p_color;
+}
+
 #endif // VTEXTDOCUMENTLAYOUT_H

+ 32 - 0
src/vtextedit.cpp

@@ -48,6 +48,8 @@ void VTextEdit::init()
 
     m_blockImageEnabled = false;
 
+    m_cursorBlockMode = false;
+
     m_imageMgr = new VImageResourceManager2();
 
     QTextDocument *doc = document();
@@ -84,6 +86,10 @@ 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(),
@@ -332,3 +338,29 @@ void VTextEdit::setImageLineColor(const QColor &p_color)
 {
     getLayout()->setImageLineColor(p_color);
 }
+
+void VTextEdit::setCursorBlockMode(bool p_enabled)
+{
+    if (p_enabled != m_cursorBlockMode) {
+        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);
+        }
+    }
+}
+
+void VTextEdit::setCursorBlockFg(const QColor &p_color)
+{
+    getLayout()->setCursorBlockFg(p_color);
+}
+
+void VTextEdit::setCursorBlockBg(const QColor &p_color)
+{
+    getLayout()->setCursorBlockBg(p_color);
+}

+ 8 - 0
src/vtextedit.h

@@ -56,6 +56,12 @@ public:
 
     void relayout(const QSet<int> &p_blocks);
 
+    void setCursorBlockMode(bool p_enabled);
+
+    void setCursorBlockFg(const QColor &p_color);
+
+    void setCursorBlockBg(const QColor &p_color);
+
 protected:
     void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE;
 
@@ -78,6 +84,8 @@ private:
     VImageResourceManager2 *m_imageMgr;
 
     bool m_blockImageEnabled;
+
+    bool m_cursorBlockMode;
 };
 
 inline void VTextEdit::setLineNumberType(LineNumberType p_type)