VTextDocumentLayout: support cursor line block background

This commit is contained in:
Le Tan 2017-12-08 19:31:19 +08:00
parent 27be40a454
commit 49811cabc0
12 changed files with 192 additions and 32 deletions

View File

@ -12,6 +12,7 @@
#include "veditor.h" #include "veditor.h"
#include "utils/veditutils.h" #include "utils/veditutils.h"
#include "vconstants.h" #include "vconstants.h"
#include "vmdeditor.h"
extern VConfigManager *g_config; extern VConfigManager *g_config;
@ -2269,9 +2270,14 @@ void VVim::setMode(VimMode p_mode, bool p_clearSelection, int p_position)
m_mode = p_mode; m_mode = p_mode;
resetState(); resetState();
VMdEditor *mdEditor = dynamic_cast<VMdEditor *>(m_editor);
switch (m_mode) { switch (m_mode) {
case VimMode::Insert: case VimMode::Insert:
m_editor->setCursorBlockModeW(CursorBlock::None); m_editor->setCursorBlockModeW(CursorBlock::None);
if (mdEditor) {
mdEditor->setHighlightCursorLineBlockEnabled(false);
}
break; break;
case VimMode::Visual: case VimMode::Visual:
@ -2280,6 +2286,18 @@ void VVim::setMode(VimMode p_mode, bool p_clearSelection, int p_position)
default: default:
m_editor->setCursorBlockModeW(CursorBlock::RightSide); m_editor->setCursorBlockModeW(CursorBlock::RightSide);
if (mdEditor) {
QString color;
if (m_mode == VimMode::Normal) {
color = g_config->getEditorVimNormalBg();
} else {
color = g_config->getEditorVimVisualBg();
}
mdEditor->setCursorLineBlockBg(color);
mdEditor->setHighlightCursorLineBlockEnabled(true);
}
break; break;
} }

View File

@ -81,9 +81,10 @@ void VEditTab::wheelEvent(QWheelEvent *p_event)
p_event->ignore(); p_event->ignore();
} }
VEditTabInfo VEditTab::fetchTabInfo() const VEditTabInfo VEditTab::fetchTabInfo(VEditTabInfo::InfoType p_type) const
{ {
VEditTabInfo info; VEditTabInfo info;
info.m_type = p_type;
info.m_editTab = const_cast<VEditTab *>(this); info.m_editTab = const_cast<VEditTab *>(this);
return info; return info;

View File

@ -80,7 +80,7 @@ public:
} }
// Create a filled VEditTabInfo. // Create a filled VEditTabInfo.
virtual VEditTabInfo fetchTabInfo() const; virtual VEditTabInfo fetchTabInfo(VEditTabInfo::InfoType p_type = VEditTabInfo::InfoType::All) const;
const VTableOfContent &getOutline() const; const VTableOfContent &getOutline() const;

View File

@ -5,8 +5,18 @@ class VEditTab;
struct VEditTabInfo struct VEditTabInfo
{ {
enum InfoType
{
// Update all information.
All = 0,
// Update only cursor information.
Cursor
};
VEditTabInfo() VEditTabInfo()
: m_editTab(NULL), : m_type(InfoType::All),
m_editTab(NULL),
m_cursorBlockNumber(-1), m_cursorBlockNumber(-1),
m_cursorPositionInBlock(-1), m_cursorPositionInBlock(-1),
m_blockCount(-1), m_blockCount(-1),
@ -16,6 +26,7 @@ struct VEditTabInfo
void clear() void clear()
{ {
m_type = InfoType::All;
m_editTab = NULL; m_editTab = NULL;
m_cursorBlockNumber = -1; m_cursorBlockNumber = -1;
m_cursorPositionInBlock = -1; m_cursorPositionInBlock = -1;
@ -23,6 +34,8 @@ struct VEditTabInfo
m_headerIndex = -1; m_headerIndex = -1;
} }
InfoType m_type;
VEditTab *m_editTab; VEditTab *m_editTab;
// Cursor information. -1 for invalid info. // Cursor information. -1 for invalid info.

View File

@ -766,8 +766,10 @@ void VEditWindow::handleTabStatusUpdated(const VEditTabInfo &p_info)
{ {
int idx = indexOf(dynamic_cast<QWidget *>(sender())); int idx = indexOf(dynamic_cast<QWidget *>(sender()));
updateTabInfo(idx); if (p_info.m_type == VEditTabInfo::InfoType::All) {
updateAllTabsSequence(); updateTabInfo(idx);
updateAllTabsSequence();
}
if (idx == currentIndex()) { if (idx == currentIndex()) {
// Current tab. Propogate its status. // Current tab. Propogate its status.

View File

@ -1880,32 +1880,35 @@ void VMainWindow::handleAreaTabStatusUpdated(const VEditTabInfo &p_info)
m_curFile = NULL; m_curFile = NULL;
} }
updateActionsStateFromTab(m_curTab); if (p_info.m_type == VEditTabInfo::InfoType::All) {
updateActionsStateFromTab(m_curTab);
m_attachmentList->setFile(dynamic_cast<VNoteFile *>(m_curFile.data())); m_attachmentList->setFile(dynamic_cast<VNoteFile *>(m_curFile.data()));
QString title; QString title;
if (m_curFile) { if (m_curFile) {
m_findReplaceDialog->updateState(m_curFile->getDocType(), m_findReplaceDialog->updateState(m_curFile->getDocType(),
m_curTab->isEditMode()); m_curTab->isEditMode());
if (m_curFile->getType() == FileType::Note) { if (m_curFile->getType() == FileType::Note) {
const VNoteFile *tmpFile = dynamic_cast<const VNoteFile *>((VFile *)m_curFile); const VNoteFile *tmpFile = dynamic_cast<const VNoteFile *>((VFile *)m_curFile);
title = QString("[%1] %2").arg(tmpFile->getNotebookName()).arg(tmpFile->fetchPath()); title = QString("[%1] %2").arg(tmpFile->getNotebookName()).arg(tmpFile->fetchPath());
} else { } else {
title = QString("%1").arg(m_curFile->fetchPath()); title = QString("%1").arg(m_curFile->fetchPath());
}
if (!m_curFile->isModifiable()) {
title.append('#');
}
if (m_curTab->isModified()) {
title.append('*');
}
} }
if (!m_curFile->isModifiable()) { updateWindowTitle(title);
title.append('#');
}
if (m_curTab->isModified()) {
title.append('*');
}
} }
updateWindowTitle(title);
updateStatusInfo(p_info); updateStatusInfo(p_info);
} }
@ -2418,7 +2421,9 @@ void VMainWindow::updateStatusInfo(const VEditTabInfo &p_info)
m_tabIndicator->show(); m_tabIndicator->show();
if (m_curTab->isEditMode()) { if (m_curTab->isEditMode()) {
m_curTab->requestUpdateVimStatus(); if (p_info.m_type == VEditTabInfo::InfoType::All) {
m_curTab->requestUpdateVimStatus();
}
} else { } else {
m_vimIndicator->hide(); m_vimIndicator->hide();
} }

View File

@ -423,7 +423,7 @@ void VMdTab::setupMarkdownEditor()
connect(m_editor, &VMdEditor::textChanged, connect(m_editor, &VMdEditor::textChanged,
this, &VMdTab::updateStatus); this, &VMdTab::updateStatus);
connect(m_editor, &VMdEditor::cursorPositionChanged, connect(m_editor, &VMdEditor::cursorPositionChanged,
this, &VMdTab::updateStatus); this, &VMdTab::updateCursorStatus);
connect(g_mainWin, &VMainWindow::editorConfigUpdated, connect(g_mainWin, &VMainWindow::editorConfigUpdated,
m_editor, &VMdEditor::updateConfig); m_editor, &VMdEditor::updateConfig);
connect(m_editor->object(), &VEditorObject::saveAndRead, connect(m_editor->object(), &VEditorObject::saveAndRead,
@ -702,9 +702,9 @@ void VMdTab::requestUpdateVimStatus()
} }
} }
VEditTabInfo VMdTab::fetchTabInfo() const VEditTabInfo VMdTab::fetchTabInfo(VEditTabInfo::InfoType p_type) const
{ {
VEditTabInfo info = VEditTab::fetchTabInfo(); VEditTabInfo info = VEditTab::fetchTabInfo(p_type);
if (m_editor) { if (m_editor) {
QTextCursor cursor = m_editor->textCursor(); QTextCursor cursor = m_editor->textCursor();
@ -972,3 +972,8 @@ bool VMdTab::checkPreviousBackupFile()
return true; return true;
} }
void VMdTab::updateCursorStatus()
{
emit statusUpdated(fetchTabInfo(VEditTabInfo::InfoType::Cursor));
}

View File

@ -69,7 +69,7 @@ public:
void decorateText(TextDecoration p_decoration, int p_level = -1) Q_DECL_OVERRIDE; void decorateText(TextDecoration p_decoration, int p_level = -1) Q_DECL_OVERRIDE;
// Create a filled VEditTabInfo. // Create a filled VEditTabInfo.
VEditTabInfo fetchTabInfo() const Q_DECL_OVERRIDE; VEditTabInfo fetchTabInfo(VEditTabInfo::InfoType p_type = VEditTabInfo::InfoType::All) const Q_DECL_OVERRIDE;
// Enable or disable heading sequence. // Enable or disable heading sequence.
void enableHeadingSequence(bool p_enabled); void enableHeadingSequence(bool p_enabled);
@ -179,6 +179,9 @@ private:
// Return true if we could continue. // Return true if we could continue.
bool checkPreviousBackupFile(); bool checkPreviousBackupFile();
// updateStatus() with only cursor position information.
void updateCursorStatus();
VMdEditor *m_editor; VMdEditor *m_editor;
VWebView *m_webViewer; VWebView *m_webViewer;
VDocument *m_document; VDocument *m_document;

View File

@ -34,7 +34,10 @@ VTextDocumentLayout::VTextDocumentLayout(QTextDocument *p_doc,
m_imageLineColor("#9575CD"), m_imageLineColor("#9575CD"),
m_cursorBlockMode(CursorBlock::None), m_cursorBlockMode(CursorBlock::None),
m_virtualCursorBlockWidth(8), m_virtualCursorBlockWidth(8),
m_lastCursorBlockWidth(-1) m_lastCursorBlockWidth(-1),
m_highlightCursorLineBlock(false),
m_cursorLineBlockBg("#C0C0C0"),
m_cursorLineBlockNumber(-1)
{ {
} }
@ -219,7 +222,11 @@ void VTextDocumentLayout::draw(QPainter *p_painter, const PaintContext &p_contex
QTextBlockFormat blockFormat = block.blockFormat(); QTextBlockFormat blockFormat = block.blockFormat();
QBrush bg = blockFormat.background(); QBrush bg = blockFormat.background();
if (bg != Qt::NoBrush) { if (bg != Qt::NoBrush) {
fillBackground(p_painter, rect, bg); int x = offset.x();
int y = offset.y();
fillBackground(p_painter,
rect.adjusted(x, y, x, y),
bg);
} }
auto selections = formatRangeFromSelection(block, p_context.selections); auto selections = formatRangeFromSelection(block, p_context.selections);
@ -252,6 +259,16 @@ void VTextDocumentLayout::draw(QPainter *p_painter, const PaintContext &p_contex
} }
} }
// Draw cursor line block.
if (m_highlightCursorLineBlock
&& m_cursorLineBlockNumber == block.blockNumber()) {
int x = offset.x();
int y = offset.y();
fillBackground(p_painter,
rect.adjusted(x, y, x, y),
m_cursorLineBlockBg);
}
layout->draw(p_painter, layout->draw(p_painter,
offset, offset,
selections, selections,
@ -1090,3 +1107,15 @@ int VTextDocumentLayout::getTextWidthWithinTextLine(const QTextLayout *p_layout,
Q_ASSERT(p_pos + p_length <= line.textStart() + line.textLength()); Q_ASSERT(p_pos + p_length <= line.textStart() + line.textLength());
return line.cursorToX(p_pos + p_length) - line.cursorToX(p_pos); return line.cursorToX(p_pos + p_length) - line.cursorToX(p_pos);
} }
void VTextDocumentLayout::updateBlockByNumber(int p_blockNumber)
{
if (p_blockNumber == -1) {
return;
}
QTextBlock block = document()->findBlockByNumber(p_blockNumber);
if (block.isValid()) {
emit updateBlock(block);
}
}

View File

@ -61,6 +61,15 @@ public:
void clearLastCursorBlockWidth(); void clearLastCursorBlockWidth();
void setHighlightCursorLineBlockEnabled(bool p_enabled);
void setCursorLineBlockBg(const QColor &p_bg);
void setCursorLineBlockNumber(int p_blockNumber);
// Request update block by block number.
void updateBlockByNumber(int p_blockNumber);
signals: signals:
// Emit to update current cursor block width if m_cursorBlockMode is enabled. // Emit to update current cursor block width if m_cursorBlockMode is enabled.
void cursorBlockWidthUpdated(int p_width); void cursorBlockWidthUpdated(int p_width);
@ -287,6 +296,15 @@ private:
int m_virtualCursorBlockWidth; int m_virtualCursorBlockWidth;
int m_lastCursorBlockWidth; int m_lastCursorBlockWidth;
// Whether highlight the block containing the cursor line.
bool m_highlightCursorLineBlock;
// The cursor line's block background color.
QColor m_cursorLineBlockBg;
// The block containing the cursor.
int m_cursorLineBlockNumber;
}; };
inline qreal VTextDocumentLayout::getLineLeading() const inline qreal VTextDocumentLayout::getLineLeading() const
@ -320,4 +338,37 @@ inline void VTextDocumentLayout::clearLastCursorBlockWidth()
{ {
m_lastCursorBlockWidth = -1; m_lastCursorBlockWidth = -1;
} }
inline void VTextDocumentLayout::setHighlightCursorLineBlockEnabled(bool p_enabled)
{
if (m_highlightCursorLineBlock != p_enabled) {
m_highlightCursorLineBlock = p_enabled;
if (!m_highlightCursorLineBlock) {
int pre = m_cursorLineBlockNumber;
m_cursorLineBlockNumber = -1;
updateBlockByNumber(pre);
}
}
}
inline void VTextDocumentLayout::setCursorLineBlockBg(const QColor &p_bg)
{
if (p_bg != m_cursorLineBlockBg) {
m_cursorLineBlockBg = p_bg;
updateBlockByNumber(m_cursorLineBlockNumber);
}
}
inline void VTextDocumentLayout::setCursorLineBlockNumber(int p_blockNumber)
{
if (p_blockNumber != m_cursorLineBlockNumber) {
int pre = m_cursorLineBlockNumber;
m_cursorLineBlockNumber = p_blockNumber;
if (m_highlightCursorLineBlock) {
updateBlockByNumber(pre);
updateBlockByNumber(m_cursorLineBlockNumber);
}
}
}
#endif // VTEXTDOCUMENTLAYOUT_H #endif // VTEXTDOCUMENTLAYOUT_H

View File

@ -51,6 +51,8 @@ void VTextEdit::init()
m_cursorBlockMode = CursorBlock::None; m_cursorBlockMode = CursorBlock::None;
m_highlightCursorLineBlock = false;
m_imageMgr = new VImageResourceManager2(); m_imageMgr = new VImageResourceManager2();
QTextDocument *doc = document(); QTextDocument *doc = document();
@ -80,7 +82,14 @@ void VTextEdit::init()
connect(verticalScrollBar(), &QScrollBar::valueChanged, connect(verticalScrollBar(), &QScrollBar::valueChanged,
this, &VTextEdit::updateLineNumberArea); this, &VTextEdit::updateLineNumberArea);
connect(this, &QTextEdit::cursorPositionChanged, connect(this, &QTextEdit::cursorPositionChanged,
this, &VTextEdit::updateLineNumberArea); this, [this]() {
if (m_highlightCursorLineBlock) {
QTextCursor cursor = textCursor();
getLayout()->setCursorLineBlockNumber(cursor.block().blockNumber());
}
updateLineNumberArea();
});
} }
VTextDocumentLayout *VTextEdit::getLayout() const VTextDocumentLayout *VTextEdit::getLayout() const
@ -356,3 +365,21 @@ void VTextEdit::setCursorBlockMode(CursorBlock p_mode)
: 1); : 1);
} }
} }
void VTextEdit::setHighlightCursorLineBlockEnabled(bool p_enabled)
{
if (m_highlightCursorLineBlock != p_enabled) {
auto layout = getLayout();
m_highlightCursorLineBlock = p_enabled;
layout->setHighlightCursorLineBlockEnabled(p_enabled);
if (m_highlightCursorLineBlock) {
QTextCursor cursor = textCursor();
layout->setCursorLineBlockNumber(cursor.block().blockNumber());
}
}
}
void VTextEdit::setCursorLineBlockBg(const QColor &p_bg)
{
getLayout()->setCursorLineBlockBg(p_bg);
}

View File

@ -59,6 +59,10 @@ public:
void setCursorBlockMode(CursorBlock p_mode); void setCursorBlockMode(CursorBlock p_mode);
void setHighlightCursorLineBlockEnabled(bool p_enabled);
void setCursorLineBlockBg(const QColor &p_bg);
protected: protected:
void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE; void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE;
@ -83,6 +87,8 @@ private:
bool m_blockImageEnabled; bool m_blockImageEnabled;
CursorBlock m_cursorBlockMode; CursorBlock m_cursorBlockMode;
bool m_highlightCursorLineBlock;
}; };
inline void VTextEdit::setLineNumberType(LineNumberType p_type) inline void VTextEdit::setLineNumberType(LineNumberType p_type)