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

View File

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

View File

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

View File

@ -5,8 +5,18 @@ class VEditTab;
struct VEditTabInfo
{
enum InfoType
{
// Update all information.
All = 0,
// Update only cursor information.
Cursor
};
VEditTabInfo()
: m_editTab(NULL),
: m_type(InfoType::All),
m_editTab(NULL),
m_cursorBlockNumber(-1),
m_cursorPositionInBlock(-1),
m_blockCount(-1),
@ -16,6 +26,7 @@ struct VEditTabInfo
void clear()
{
m_type = InfoType::All;
m_editTab = NULL;
m_cursorBlockNumber = -1;
m_cursorPositionInBlock = -1;
@ -23,6 +34,8 @@ struct VEditTabInfo
m_headerIndex = -1;
}
InfoType m_type;
VEditTab *m_editTab;
// 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()));
updateTabInfo(idx);
updateAllTabsSequence();
if (p_info.m_type == VEditTabInfo::InfoType::All) {
updateTabInfo(idx);
updateAllTabsSequence();
}
if (idx == currentIndex()) {
// Current tab. Propogate its status.

View File

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

View File

@ -423,7 +423,7 @@ void VMdTab::setupMarkdownEditor()
connect(m_editor, &VMdEditor::textChanged,
this, &VMdTab::updateStatus);
connect(m_editor, &VMdEditor::cursorPositionChanged,
this, &VMdTab::updateStatus);
this, &VMdTab::updateCursorStatus);
connect(g_mainWin, &VMainWindow::editorConfigUpdated,
m_editor, &VMdEditor::updateConfig);
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) {
QTextCursor cursor = m_editor->textCursor();
@ -972,3 +972,8 @@ bool VMdTab::checkPreviousBackupFile()
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;
// 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.
void enableHeadingSequence(bool p_enabled);
@ -179,6 +179,9 @@ private:
// Return true if we could continue.
bool checkPreviousBackupFile();
// updateStatus() with only cursor position information.
void updateCursorStatus();
VMdEditor *m_editor;
VWebView *m_webViewer;
VDocument *m_document;

View File

@ -34,7 +34,10 @@ VTextDocumentLayout::VTextDocumentLayout(QTextDocument *p_doc,
m_imageLineColor("#9575CD"),
m_cursorBlockMode(CursorBlock::None),
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();
QBrush bg = blockFormat.background();
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);
@ -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,
offset,
selections,
@ -1090,3 +1107,15 @@ int VTextDocumentLayout::getTextWidthWithinTextLine(const QTextLayout *p_layout,
Q_ASSERT(p_pos + p_length <= line.textStart() + line.textLength());
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 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:
// Emit to update current cursor block width if m_cursorBlockMode is enabled.
void cursorBlockWidthUpdated(int p_width);
@ -287,6 +296,15 @@ private:
int m_virtualCursorBlockWidth;
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
@ -320,4 +338,37 @@ inline void VTextDocumentLayout::clearLastCursorBlockWidth()
{
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

View File

@ -51,6 +51,8 @@ void VTextEdit::init()
m_cursorBlockMode = CursorBlock::None;
m_highlightCursorLineBlock = false;
m_imageMgr = new VImageResourceManager2();
QTextDocument *doc = document();
@ -80,7 +82,14 @@ void VTextEdit::init()
connect(verticalScrollBar(), &QScrollBar::valueChanged,
this, &VTextEdit::updateLineNumberArea);
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
@ -356,3 +365,21 @@ void VTextEdit::setCursorBlockMode(CursorBlock p_mode)
: 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 setHighlightCursorLineBlockEnabled(bool p_enabled);
void setCursorLineBlockBg(const QColor &p_bg);
protected:
void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE;
@ -83,6 +87,8 @@ private:
bool m_blockImageEnabled;
CursorBlock m_cursorBlockMode;
bool m_highlightCursorLineBlock;
};
inline void VTextEdit::setLineNumberType(LineNumberType p_type)