- Enhancement: Optimization for drawing scrollbars.

This commit is contained in:
Roy Qu 2024-03-06 12:01:56 +08:00
parent 0e77ed10c7
commit 383031bc5d
5 changed files with 94 additions and 41 deletions

View File

@ -85,6 +85,7 @@ Red Panda C++ Version 2.26
- Fix: Function list is not correctly retrived for full-scoped functions. - Fix: Function list is not correctly retrived for full-scoped functions.
- Enhancement: Improved Raw string support - Enhancement: Improved Raw string support
- Enhancement: New option for compiler set "Don't localize gcc output messages" - Enhancement: New option for compiler set "Don't localize gcc output messages"
- Enhancement: Optimization for drawing scrollbars.
Red Panda C++ Version 2.25 Red Panda C++ Version 2.25

View File

@ -91,7 +91,9 @@ int Document::lineWidth(int line)
{ {
QMutexLocker locker(&mMutex); QMutexLocker locker(&mMutex);
if (line>=0 && line < mLines.size()) { if (line>=0 && line < mLines.size()) {
return mLines[line]->width(); int width = mLines[line]->width();
//updateLongestLineWidth(width);
return width;
} else } else
return 0; return 0;
} }
@ -139,17 +141,14 @@ int Document::blockEnded(int line)
return 0; return 0;
} }
int Document::longestLineWidth() { int Document::maxLineWidth() {
QMutexLocker locker(&mMutex); QMutexLocker locker(&mMutex);
if (mIndexOfLongestLine < 0) { if (mIndexOfLongestLine < 0) {
int MaxLen = -1; int MaxLen = -1;
mIndexOfLongestLine = -1; mIndexOfLongestLine = -1;
if (mLines.count() > 0 ) { if (mLines.count() > 0 ) {
for (int i=0;i<mLines.size();i++) { for (int i=0;i<mLines.size();i++) {
int len = mLines[i]->width(); int len = mLines[i]->mWidth;
//Just estimate it.
if (len<0)
len = mCharWidth * mLines[i]->lineText().length();
if (len > MaxLen) { if (len > MaxLen) {
MaxLen = len; MaxLen = len;
mIndexOfLongestLine = i; mIndexOfLongestLine = i;
@ -471,9 +470,9 @@ void Document::putLine(int index, const QString &s, bool notify) {
listIndexOutOfBounds(index); listIndexOutOfBounds(index);
} }
beginUpdate(); beginUpdate();
int oldColumns = mLines[index]->width(); int oldWidth = mLines[index]->width();
mLines[index]->setLineText( s ); mLines[index]->setLineText( s );
if (mIndexOfLongestLine == index && oldColumns>mLines[index]->width() ) if (mIndexOfLongestLine == index && oldWidth>mLines[index]->width() )
mIndexOfLongestLine = -1; mIndexOfLongestLine = -1;
else if (mIndexOfLongestLine>=0 else if (mIndexOfLongestLine>=0
&& mIndexOfLongestLine<mLines.count() && mIndexOfLongestLine<mLines.count()
@ -1171,9 +1170,21 @@ void Document::setLineWidth(int line, const QString &lineText, int newWidth, con
return; return;
mLines[line]->mWidth = newWidth; mLines[line]->mWidth = newWidth;
mLines[line]->mGlyphStartPositionList = glyphStartPositionList; mLines[line]->mGlyphStartPositionList = glyphStartPositionList;
updateLongestLineWidth(line , newWidth);
Q_ASSERT(mLines[line]->mGlyphStartPositionList.length() == mLines[line]->mGlyphStartCharList.length()); Q_ASSERT(mLines[line]->mGlyphStartPositionList.length() == mLines[line]->mGlyphStartCharList.length());
} }
void Document::updateLongestLineWidth(int line, int width)
{
if (mIndexOfLongestLine<0) {
mIndexOfLongestLine = line;
emit maxLineWidthChanged(width);
} else if (mLines[mIndexOfLongestLine]->mWidth < width) {
mIndexOfLongestLine = line;
emit maxLineWidthChanged(width);
}
}
QList<int> Document::calcGlyphPositionList(const QString &lineText, const QList<int> &glyphStartCharList, int left, int &right) const QList<int> Document::calcGlyphPositionList(const QString &lineText, const QList<int> &glyphStartCharList, int left, int &right) const
{ {
return calcGlyphPositionList(lineText, glyphStartCharList, return calcGlyphPositionList(lineText, glyphStartCharList,

View File

@ -300,7 +300,7 @@ public:
* *
* @return * @return
*/ */
int longestLineWidth(); int maxLineWidth();
/** /**
* @brief get line break of the current document * @brief get line break of the current document
@ -567,6 +567,7 @@ signals:
void deleted(int startLine, int count); void deleted(int startLine, int count);
void inserted(int startLine, int count); void inserted(int startLine, int count);
void putted(int line); void putted(int line);
void maxLineWidthChanged(int newWidth);
protected: protected:
QString getTextStr() const; QString getTextStr() const;
void setUpdateState(bool Updating); void setUpdateState(bool Updating);
@ -576,6 +577,7 @@ protected:
void internalClear(); void internalClear();
private: private:
void setLineWidth(int line, const QString& lineText, int newWidth, const QList<int> glyphStartPositionList); void setLineWidth(int line, const QString& lineText, int newWidth, const QList<int> glyphStartPositionList);
void updateLongestLineWidth(int line, int width);
int glyphWidth(const QString& glyph, int left, int glyphWidth(const QString& glyph, int left,
const QFontMetrics &fontMetrics, const QFontMetrics &fontMetrics,

View File

@ -60,6 +60,10 @@ QSynEdit::QSynEdit(QWidget *parent) : QAbstractScrollArea(parent),
mFontDummy = QFont("monospace",14); mFontDummy = QFont("monospace",14);
mFontDummy.setStyleStrategy(QFont::PreferAntialias); mFontDummy.setStyleStrategy(QFont::PreferAntialias);
mDocument = std::make_shared<Document>(mFontDummy, this); mDocument = std::make_shared<Document>(mFontDummy, this);
connect(mDocument.get(), &Document::maxLineWidthChanged,
this, &QSynEdit::updateHScrollbar);
//fPlugins := TList.Create; //fPlugins := TList.Create;
mMouseMoved = false; mMouseMoved = false;
mMouseOrigin = QPoint(0,0); mMouseOrigin = QPoint(0,0);
@ -70,6 +74,11 @@ QSynEdit::QSynEdit(QWidget *parent) : QAbstractScrollArea(parent),
mDocument->connect(mDocument.get(), &Document::deleted, this, &QSynEdit::onLinesDeleted); mDocument->connect(mDocument.get(), &Document::deleted, this, &QSynEdit::onLinesDeleted);
mDocument->connect(mDocument.get(), &Document::inserted, this, &QSynEdit::onLinesInserted); mDocument->connect(mDocument.get(), &Document::inserted, this, &QSynEdit::onLinesInserted);
mDocument->connect(mDocument.get(), &Document::putted, this, &QSynEdit::onLinesPutted); mDocument->connect(mDocument.get(), &Document::putted, this, &QSynEdit::onLinesPutted);
connect(mDocument.get(), &Document::maxLineWidthChanged,
this, &QSynEdit::updateHScrollbar);
mDocument->connect(mDocument.get(), &Document::cleared, this, &QSynEdit::updateVScrollbar);
mDocument->connect(mDocument.get(), &Document::deleted, this, &QSynEdit::updateVScrollbar);
mDocument->connect(mDocument.get(), &Document::inserted, this, &QSynEdit::updateVScrollbar);
mGutterWidth = 0; mGutterWidth = 0;
mScrollBars = ScrollStyle::ssBoth; mScrollBars = ScrollStyle::ssBoth;
@ -237,6 +246,7 @@ void QSynEdit::setCaretXYEx(bool CallEnsureCursorPosVisible, BufferCoord value)
if (mCaretX != value.ch) { if (mCaretX != value.ch) {
mCaretX = value.ch; mCaretX = value.ch;
mStatusChanges.setFlag(StatusChange::scCaretX); mStatusChanges.setFlag(StatusChange::scCaretX);
mStateFlags.setFlag(StateFlag::sfHScrollbarChanged);
invalidateLine(mCaretY); invalidateLine(mCaretY);
} }
if (mCaretY != value.line) { if (mCaretY != value.line) {
@ -247,6 +257,7 @@ void QSynEdit::setCaretXYEx(bool CallEnsureCursorPosVisible, BufferCoord value)
invalidateLine(oldCaretY); invalidateLine(oldCaretY);
invalidateGutterLine(oldCaretY); invalidateGutterLine(oldCaretY);
mStatusChanges.setFlag(StatusChange::scCaretY); mStatusChanges.setFlag(StatusChange::scCaretY);
mStateFlags.setFlag(StateFlag::sfVScrollbarChanged);
} }
// Call UpdateLastCaretX before DecPaintLock because the event handler it // Call UpdateLastCaretX before DecPaintLock because the event handler it
// calls could raise an exception, and we don't want fLastCaretX to be // calls could raise an exception, and we don't want fLastCaretX to be
@ -254,8 +265,6 @@ void QSynEdit::setCaretXYEx(bool CallEnsureCursorPosVisible, BufferCoord value)
updateLastCaretX(); updateLastCaretX();
if (CallEnsureCursorPosVisible) if (CallEnsureCursorPosVisible)
ensureCursorPosVisible(); ensureCursorPosVisible();
mStateFlags.setFlag(StateFlag::sfCaretChanged);
mStateFlags.setFlag(StateFlag::sfScrollbarChanged);
} else { } else {
// Also call UpdateLastCaretX if the caret didn't move. Apps don't know // Also call UpdateLastCaretX if the caret didn't move. Apps don't know
// anything about fLastCaretX and they shouldn't need to. So, to avoid any // anything about fLastCaretX and they shouldn't need to. So, to avoid any
@ -327,7 +336,7 @@ bool QSynEdit::canRedo() const
int QSynEdit::maxScrollWidth() const int QSynEdit::maxScrollWidth() const
{ {
int maxWidth = mDocument->longestLineWidth(); int maxWidth = mDocument->maxLineWidth();
if (useCodeFolding()) if (useCodeFolding())
maxWidth += stringWidth(syntaxer()->foldString(""),maxWidth); maxWidth += stringWidth(syntaxer()->foldString(""),maxWidth);
if (mOptions.testFlag(eoScrollPastEol)) if (mOptions.testFlag(eoScrollPastEol))
@ -2969,8 +2978,16 @@ void QSynEdit::decPaintLock()
Q_ASSERT(mPaintLock > 0); Q_ASSERT(mPaintLock > 0);
mPaintLock--; mPaintLock--;
if (mPaintLock == 0 ) { if (mPaintLock == 0 ) {
if (mStateFlags.testFlag(StateFlag::sfScrollbarChanged)) { bool scrollbarUpdated = false;
updateScrollbars(); if (mStateFlags.testFlag(StateFlag::sfHScrollbarChanged)) {
updateHScrollbar();
scrollbarUpdated = true;
}
if (mStateFlags.testFlag(StateFlag::sfVScrollbarChanged)) {
updateVScrollbar();
scrollbarUpdated = true;
}
if (scrollbarUpdated) {
ensureCursorPosVisible(); ensureCursorPosVisible();
} }
if (mStateFlags.testFlag(StateFlag::sfCaretChanged)) if (mStateFlags.testFlag(StateFlag::sfCaretChanged))
@ -3117,21 +3134,19 @@ void QSynEdit::doOnStatusChange(StatusChanges)
mStatusChanges = StatusChange::scNone; mStatusChanges = StatusChange::scNone;
} }
void QSynEdit::updateScrollbars() void QSynEdit::updateHScrollbar()
{ {
int nMaxScroll; int nMaxScroll;
int nMin,nMax,nPage,nPos; int nMin,nMax,nPage,nPos;
if (mPaintLock!=0) { if (mPaintLock!=0) {
mStateFlags.setFlag(StateFlag::sfScrollbarChanged); mStateFlags.setFlag(StateFlag::sfHScrollbarChanged);
} else { } else {
mStateFlags.setFlag(StateFlag::sfScrollbarChanged,false); mStateFlags.setFlag(StateFlag::sfHScrollbarChanged,false);
if (mScrollBars != ScrollStyle::ssNone) { if (mScrollBars != ScrollStyle::ssNone) {
if (mOptions.testFlag(eoHideShowScrollbars)) { if (mOptions.testFlag(eoHideShowScrollbars)) {
setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded);
setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded);
} else { } else {
setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn);
setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn);
} }
if (mScrollBars == ScrollStyle::ssBoth || mScrollBars == ScrollStyle::ssHorizontal) { if (mScrollBars == ScrollStyle::ssBoth || mScrollBars == ScrollStyle::ssHorizontal) {
nMaxScroll = maxScrollWidth(); nMaxScroll = maxScrollWidth();
@ -3146,6 +3161,26 @@ void QSynEdit::updateScrollbars()
horizontalScrollBar()->setSingleStep(1); horizontalScrollBar()->setSingleStep(1);
} else } else
setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn);
} else {
setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
}
}
}
void QSynEdit::updateVScrollbar()
{
int nMaxScroll;
int nMin,nMax,nPage,nPos;
if (mPaintLock!=0) {
mStateFlags.setFlag(StateFlag::sfVScrollbarChanged);
} else {
mStateFlags.setFlag(StateFlag::sfVScrollbarChanged,false);
if (mScrollBars != ScrollStyle::ssNone) {
if (mOptions.testFlag(eoHideShowScrollbars)) {
setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded);
} else {
setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn);
}
if (mScrollBars == ScrollStyle::ssBoth || mScrollBars == ScrollStyle::ssVertical) { if (mScrollBars == ScrollStyle::ssBoth || mScrollBars == ScrollStyle::ssVertical) {
nMaxScroll = maxScrollHeight(); nMaxScroll = maxScrollHeight();
@ -3161,12 +3196,12 @@ void QSynEdit::updateScrollbars()
} else } else
setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
} else { } else {
setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
} }
} }
} }
void QSynEdit::updateCaret() void QSynEdit::updateCaret()
{ {
mStateFlags.setFlag(StateFlag::sfCaretChanged,false); mStateFlags.setFlag(StateFlag::sfCaretChanged,false);
@ -3363,7 +3398,8 @@ void QSynEdit::uncollapse(PCodeFoldingRange FoldRange)
// Redraw fold mark // Redraw fold mark
invalidateGutterLines(FoldRange->fromLine, INT_MAX); invalidateGutterLines(FoldRange->fromLine, INT_MAX);
updateScrollbars(); updateVScrollbar();
updateHScrollbar();
} }
void QSynEdit::collapse(PCodeFoldingRange FoldRange) void QSynEdit::collapse(PCodeFoldingRange FoldRange)
@ -3383,7 +3419,8 @@ void QSynEdit::collapse(PCodeFoldingRange FoldRange)
// Redraw fold mark // Redraw fold mark
invalidateGutterLines(FoldRange->fromLine, INT_MAX); invalidateGutterLines(FoldRange->fromLine, INT_MAX);
updateScrollbars(); updateHScrollbar();
updateVScrollbar();
} }
void QSynEdit::foldOnLinesInserted(int Line, int Count) void QSynEdit::foldOnLinesInserted(int Line, int Count)
@ -3771,17 +3808,17 @@ void QSynEdit::onSizeOrFontChanged(bool bFont)
{ {
if (mCharWidth != 0) { if (mCharWidth != 0) {
mLinesInWindow = clientHeight() / mTextHeight; mLinesInWindow = clientHeight() / mTextHeight;
bool scrollBarChangedSettings = mStateFlags.testFlag(StateFlag::sfScrollbarChanged);
if (bFont) { if (bFont) {
if (mGutter.showLineNumbers()) if (mGutter.showLineNumbers())
onGutterChanged(); onGutterChanged();
else else {
updateScrollbars(); updateHScrollbar();
}
mStateFlags.setFlag(StateFlag::sfCaretChanged,false); mStateFlags.setFlag(StateFlag::sfCaretChanged,false);
invalidate(); invalidate();
} else } else {
updateScrollbars(); updateHScrollbar();
mStateFlags.setFlag(StateFlag::sfScrollbarChanged,scrollBarChangedSettings); }
//if (!mOptions.testFlag(SynEditorOption::eoScrollPastEol)) //if (!mOptions.testFlag(SynEditorOption::eoScrollPastEol))
setLeftPos(mLeftPos); setLeftPos(mLeftPos);
//if (!mOptions.testFlag(SynEditorOption::eoScrollPastEof)) //if (!mOptions.testFlag(SynEditorOption::eoScrollPastEof))
@ -4084,7 +4121,8 @@ void QSynEdit::setOptions(const EditorOptions &Value)
setBlockBegin(vTempBlockBegin); setBlockBegin(vTempBlockBegin);
setBlockEnd(vTempBlockEnd); setBlockEnd(vTempBlockEnd);
} }
updateScrollbars(); updateHScrollbar();
updateVScrollbar();
if (bUpdateAll) if (bUpdateAll)
invalidate(); invalidate();
decPaintLock(); decPaintLock();
@ -6577,7 +6615,6 @@ void QSynEdit::onLinesChanged()
SelectionMode vOldMode; SelectionMode vOldMode;
mStateFlags.setFlag(StateFlag::sfLinesChanging, false); mStateFlags.setFlag(StateFlag::sfLinesChanging, false);
updateScrollbars();
if (mActiveSelectionMode == SelectionMode::Column) { if (mActiveSelectionMode == SelectionMode::Column) {
BufferCoord oldBlockStart = blockBegin(); BufferCoord oldBlockStart = blockBegin();
BufferCoord oldBlockEnd = blockEnd(); BufferCoord oldBlockEnd = blockEnd();
@ -6741,7 +6778,7 @@ void QSynEdit::setBlockEnd(BufferCoord value)
else else
value.ch = 1; value.ch = 1;
} else { } else {
int maxLen = mDocument->longestLineWidth(); int maxLen = mDocument->maxLineWidth();
if (useCodeFolding()) if (useCodeFolding())
maxLen += stringWidth(mSyntaxer->foldString(""),maxLen); maxLen += stringWidth(mSyntaxer->foldString(""),maxLen);
value.ch = minMax(value.ch, 1, maxLen+1); value.ch = minMax(value.ch, 1, maxLen+1);
@ -6848,7 +6885,7 @@ void QSynEdit::setBlockBegin(BufferCoord value)
else else
value.ch = 1; value.ch = 1;
} else { } else {
int maxLen = mDocument->longestLineWidth(); int maxLen = mDocument->maxLineWidth();
if (useCodeFolding()) if (useCodeFolding())
maxLen += stringWidth(mSyntaxer->foldString(""),maxLen); maxLen += stringWidth(mSyntaxer->foldString(""),maxLen);
value.ch = minMax(value.ch, 1, maxLen+1); value.ch = minMax(value.ch, 1, maxLen+1);

View File

@ -62,14 +62,15 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(StatusChanges)
enum class StateFlag { enum class StateFlag {
sfCaretChanged = 0x0001, sfCaretChanged = 0x0001,
sfScrollbarChanged = 0x0002, sfHScrollbarChanged = 0x0002,
sfLinesChanging = 0x0004, sfVScrollbarChanged = 0x0004,
sfIgnoreNextChar = 0x0008, sfLinesChanging = 0x0008,
sfCaretVisible = 0x0010, sfIgnoreNextChar = 0x0010,
sfDblClicked = 0x0020, sfCaretVisible = 0x0020,
sfWaitForDragging = 0x0040, sfDblClicked = 0x0040,
sfRedrawNeeded = 0x0080, sfWaitForDragging = 0x0080,
sfGutterRedrawNeeded = 0x0100, sfRedrawNeeded = 0x0100,
sfGutterRedrawNeeded = 0x0200,
}; };
Q_DECLARE_FLAGS(StateFlags,StateFlag) Q_DECLARE_FLAGS(StateFlags,StateFlag)
@ -533,7 +534,8 @@ private:
void internalSetCaretY(int Value); void internalSetCaretY(int Value);
void setStatusChanged(StatusChanges changes); void setStatusChanged(StatusChanges changes);
void doOnStatusChange(StatusChanges changes); void doOnStatusChange(StatusChanges changes);
void updateScrollbars(); void updateHScrollbar();
void updateVScrollbar();
void updateCaret(); void updateCaret();
void recalcCharExtent(); void recalcCharExtent();
QString expandAtWideGlyphs(const QString& S); QString expandAtWideGlyphs(const QString& S);