From b2a435297d29c2fd47bb2de2b16e96901127bc6e Mon Sep 17 00:00:00 2001 From: Le Tan Date: Thu, 30 Nov 2017 21:25:43 +0800 Subject: [PATCH] VTextEdit: support block cursor --- src/vtextdocumentlayout.cpp | 38 +++++++++++++++++++++++++++++-------- src/vtextdocumentlayout.h | 34 +++++++++++++++++++++++++++++++++ src/vtextedit.cpp | 32 +++++++++++++++++++++++++++++++ src/vtextedit.h | 8 ++++++++ 4 files changed, 104 insertions(+), 8 deletions(-) diff --git a/src/vtextdocumentlayout.cpp b/src/vtextdocumentlayout.cpp index 8355123f..55fd3806 100644 --- a/src/vtextdocumentlayout.cpp +++ b/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(); diff --git a/src/vtextdocumentlayout.h b/src/vtextdocumentlayout.h index b423312a..66e2e591 100644 --- a/src/vtextdocumentlayout.h +++ b/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 diff --git a/src/vtextedit.cpp b/src/vtextedit.cpp index 6c7a1e3e..0c8b66c9 100644 --- a/src/vtextedit.cpp +++ b/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); +} diff --git a/src/vtextedit.h b/src/vtextedit.h index bda36798..73d35084 100644 --- a/src/vtextedit.h +++ b/src/vtextedit.h @@ -56,6 +56,12 @@ public: void relayout(const QSet &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)